/*
Cross Platform Core Code.

Copyright(R) 2012-2015 Sumscope Software.
All rights reserved.

Using:
class	CBondInfoArray;
class	CBondContainer;
class	CDomain;
class	CDomainContainer;

线程安全:
	除一下几个接口,都是线程安全的,所有非线程安全的函数开头有//NEED*的注释,搜索即可
	GetBondInfoByKeyEx
	GetAdditionBondInfo
	ElementAt
	GetBond
	IsHyHasPrice
	GetMaturityRangeEx
const参数:
	除了UpdateContainer接口的condStr,其他的所有BLHCONDITION参数都改为const引用

const成员函数:

大循环
	所有带有大循环的for语句右侧都增加了//BIGLOOP注释
	对于大循环锁,需要以下四个参数:
		开始拿锁的时间
		拿到锁的时间
		释放锁的时间
		代码的名称
		释放锁的时候,其他所有等待此锁的线程的名称,和等待时间
	而且,使用一个宏开关,就可以移除这些功能



*/
#define NOMINMAX
#include "qbprotocol/include/SSFilters.h"
#include "BondContainer.h"
#include "BondOptionInfo.h"
#include "BondAuctionInfo.h"
#include "AdditionBondInfo.h"
#include "ABSBondInfo.h"
#include "SSCompanyReportManager.h"
#include "BondCDCPriceInfo.h"
#include "SSVContainer.h"
#include <algorithm>
#include <mutex>
#include <core/container/SHash.h>
#include <core/container/LevelList.h>
#include <core/time/time.h>
#include <core/system/system_util.h>
#include <uam/ServerTimeMgr.h>
#include <uam/UserAccountManager.h>
#include <QDateTime>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
//#define new DEBUG_NEW
#endif


#ifdef BONDINFO_STAT
#include "./BondField/BondInfoStat.h"
#define USE_BOND(OBJ,INDEX)	BondInfoStat::AddBondUse(sizeof(OBJ),INDEX,__FUNCTION__,__LINE__)
#else
#define USE_BOND(OBJ,INDEX)
#endif
//////////////////////////////////////////////////////////////////////
#include "QBIssuerInfo.h"
#include "QBProviceInfo.h"
#include "QBBondCrmClause.h"
#include "BondCalendar.h"
#include "BondCSIPriceInfo.h"
// class CBondContainer

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

const int g_nMaxSize = 204800;
const int g_nMaxAddiSize = 8192;
const int g_nMaxOptionInfoSize = 16384;//16K
const int g_nMaxAuctionInfoSize = 16384;//16K

const char CBondContainer::lmCIB[] = "CIB";
const char CBondContainer::lmSSE[] = "SSE";
const char CBondContainer::lmSZE[] = "SZE";

#ifdef WIN32
#define FMTBUF(buf,fmt,...)		_snprintf_s(buf,_countof(buf),-1,fmt,##__VA_ARGS__)
#else
#define FMTBUF(buf,fmt,...)		snprintf(buf,_countof(buf),fmt,##__VA_ARGS__)
#endif

namespace{
//#define SSBONDNET_LOG
#ifdef SSBONDNET_LOG
#define NETLOG(format , ...) LOGWRITE(kLogLevelDebug , format , ##__VA_ARGS__) 
#else
#define NETLOG(format , ...)
#endif
	inline bool IsEmpty(const char* str){
		return (str == nullptr || *str == '\0');
	}

	bool IsInToday(CBondContainer* pBondContainer,const char* args_time)
	{
		if (pBondContainer==nullptr || args_time == nullptr||IsEmpty(args_time))
			return false;
		
		struct tm stTm;
		time_t tSeverTime = ServerTimeMgr::instance().serverTime();
		#ifdef WIN32
		localtime_s(&stTm, &tSeverTime);
		#else
		localtime_r(&tSeverTime, &stTm);
		#endif

		char strTime[12] = { 0 };
		strftime(strTime, 12, "%Y%m%d", &stTm);
		if (strcmp(strTime, args_time) == 0) return true;

		return true;
	}

	bool IsSplitBondInfoEnable(){
		static bool init = false;
		static bool enable = false;
		if (!init)
		{
			enable = false;// boolTEST(kProfileSplitBondInfo);
			init = true;
		}
		return enable;
	}

	enum kTypeCategory
	{
		kTypeCategoryCoupon		= 0,			//
		kTypeCategoryProd		= 1,			//
		kTypeCategoryRating		= 2,			//
		kTypeCategoryInst		= 3,			//	
		kTypeCategoryMax		= 4,			//
		kTypeCategoryCDCRating	= 5,
		kTypeCategoryCSIRating	= 6,
		kTypeCategoryCBRRating	= 7,
	};
	class TypeNameManager
	{
		CSPString		m_coupon_names[CBondContainer::CouponMax + 1];
		CSPString		m_prod_names[CBondContainer::ProdMax+1];
		CSPString		m_rating_names[CBondContainer::RatingMax+1];
		CSPString		m_inst_names[CBondContainer::InstMax+1];
		CSPString		m_cdcrating_names[CBondContainer::CDCRatingMax + 1];
		CSPString		m_csirating_names[CBondContainer::CSIRatingMax + 1];
		CSPString		m_cbrrating_names[CBondContainer::CBRRatingMax + 1];
		CSPString		m_blank;
		bool			m_initialized;
		std::mutex		m_lock;
	public:
		static TypeNameManager& Get()
		{
			static TypeNameManager tnm;
			return tnm;
		}
		TypeNameManager():m_initialized(false){}
		~TypeNameManager()
		{

		}
		bool IsRatingEqual(CBondContainer::IssuerRating filter, const char* ratting)
		{
			Prepare();
			if (filter == CBondContainer::RatingAll)return true;
			else if (filter == CBondContainer::RatingNone)return false;
			else if (filter == CBondContainer::RatingOther)
			{
				if (IsEmpty(ratting))
					return true;
				if (ratting)
				{
					if (strcmp(ratting, "CCL") == 0)
						return true;
					if (strcmp(m_rating_names[CBondContainer::RatingAAAP].c_str(), ratting) == 0 ||
						strcmp(m_rating_names[CBondContainer::RatingAAA].c_str(), ratting) == 0 ||
						strcmp(m_rating_names[CBondContainer::RatingAAP].c_str(), ratting) == 0 ||
						strcmp(m_rating_names[CBondContainer::RatingAA].c_str(), ratting) == 0 ||
						strcmp(m_rating_names[CBondContainer::RatingAAN].c_str(), ratting) == 0 ||
						strcmp(m_rating_names[CBondContainer::RatingAP].c_str(), ratting) == 0)
						return false;
				}	
				return true;
			}
			else if (filter>CBondContainer::RatingAll && filter<CBondContainer::RatingOther)
			{
				return ratting && strcmp(m_rating_names[filter].c_str(), ratting)==0;
			}
			return false;
		}

		bool IsCDCRatingEqual(CBondContainer::CDCRating filter, const char* ratting)
		{
			Prepare();
			if (filter == CBondContainer::CDCRatingAll)return true;
			else if (filter == CBondContainer::CDCRatingNone)return false;
			else if (filter == CBondContainer::CDCRatingOther)
			{
				if (IsEmpty(ratting))
					return true;
				if (ratting)
				{
					if (strcmp(m_cdcrating_names[CBondContainer::CDCRatingAAAP].c_str(), ratting) == 0 ||
						strcmp(m_cdcrating_names[CBondContainer::CDCRatingAAA].c_str(), ratting) == 0 ||
						strcmp(m_cdcrating_names[CBondContainer::CDCRatingAAAM].c_str(), ratting) == 0 ||
						strcmp(m_cdcrating_names[CBondContainer::CDCRatingAAP].c_str(), ratting) == 0 ||
						strcmp(m_cdcrating_names[CBondContainer::CDCRatingAA].c_str(), ratting) == 0 ||
						strcmp(m_cdcrating_names[CBondContainer::CDCRatingAA2].c_str(), ratting) == 0 ||
						strcmp(m_cdcrating_names[CBondContainer::CDCRatingAAM].c_str(), ratting) == 0)
						return false;
				}
				return true;
			}
			else if (filter > CBondContainer::CDCRatingAll && filter < CBondContainer::CDCRatingOther)
			{
				bool bRet = (ratting && strcmp(m_cdcrating_names[filter].c_str(), ratting) == 0);
				return bRet;
			}
			return false;
		}

		bool IsCSIRatingEqual(CBondContainer::CSIRating filter, const char* ratting)
		{
			Prepare();
			if (filter == CBondContainer::CSIRatingAll)return true;
			else if (filter == CBondContainer::CSIRatingNone)return false;
			else if (filter == CBondContainer::CSIRatingOther)
			{
				if (IsEmpty(ratting))
					return true;
				if (ratting)
				{
					if (strcmp(m_csirating_names[CBondContainer::CSIRatingAAAP].c_str(), ratting) == 0 ||
						strcmp(m_csirating_names[CBondContainer::CSIRatingAAA].c_str(), ratting) == 0 ||
						strcmp(m_csirating_names[CBondContainer::CSIRatingAAP].c_str(), ratting) == 0 ||
						strcmp(m_csirating_names[CBondContainer::CSIRatingAA].c_str(), ratting) == 0 ||
						strcmp(m_csirating_names[CBondContainer::CSIRatingAA2].c_str(), ratting) == 0 ||
						strcmp(m_csirating_names[CBondContainer::CSIRatingAAM].c_str(), ratting) == 0)
						return false;
				}
				return true;
			}
			else if (filter > CBondContainer::CSIRatingAll && filter < CBondContainer::CSIRatingOther)
			{
				return ratting && strcmp(m_csirating_names[filter].c_str(), ratting) == 0;
			}
			return false;
		}

		bool IsCBRRatingEqual(CBondContainer::CBRRating filter, const char* ratting)
		{
			Prepare();
			if (filter == CBondContainer::CBRRatingAll)return true;
			else if (filter == CBondContainer::CBRRatingNone)return false;
			else if (filter == CBondContainer::CBRRatingOther)
			{
				if (IsEmpty(ratting))
					return true;
				if (ratting)
				{
					if (strcmp(m_cbrrating_names[CBondContainer::CBRRatingAAAP].c_str(), ratting) == 0 ||
						strcmp(m_cbrrating_names[CBondContainer::CBRRatingAAA].c_str(), ratting) == 0 ||
						strcmp(m_cbrrating_names[CBondContainer::CBRRatingAAAM].c_str(), ratting) == 0 ||
						strcmp(m_cbrrating_names[CBondContainer::CBRRatingAAP].c_str(), ratting) == 0 ||
						strcmp(m_cbrrating_names[CBondContainer::CBRRatingAA].c_str(), ratting) == 0 ||
						strcmp(m_cbrrating_names[CBondContainer::CBRRatingAAM].c_str(), ratting) == 0||
						strcmp(m_cbrrating_names[CBondContainer::CBRRatingAP].c_str(), ratting) == 0)
						return false;
				}
				return true;
			}
			else if (filter > CBondContainer::CBRRatingAll && filter < CBondContainer::CBRRatingOther)
			{
				return ratting && strcmp(m_cbrrating_names[filter].c_str(), ratting) == 0;
			}
			return false;
		}

		const CSPString&	GetTypeName(kTypeCategory category,uint32_t nType )
		{
			Prepare();
			switch (category)
			{
			case kTypeCategoryCoupon:return m_coupon_names[nType]; break;
			case kTypeCategoryProd:return m_prod_names[nType]; break;
			case kTypeCategoryRating:return m_rating_names[nType]; break;
			case kTypeCategoryInst:return m_inst_names[nType]; break;
			case kTypeCategoryCDCRating:return m_cdcrating_names[nType]; break;
			case kTypeCategoryCSIRating:return m_csirating_names[nType]; break;
			case kTypeCategoryCBRRating:return m_cbrrating_names[nType]; break;
			default:break;
			}
			return m_blank;
		}
	protected:
		inline void Prepare()
		{
			if (!m_initialized)
			{
				std::lock_guard<std::mutex> locker(m_lock);
				if (!m_initialized)
				{
					Init();
					m_initialized = true;
				}
			}
		}
		void Init()
		{
			AddTypeName(kTypeCategoryCoupon,CBondContainer::CouponNon,"");
			AddTypeName(kTypeCategoryCoupon,CBondContainer::CouponAll,"ALL");
			AddTypeName(kTypeCategoryCoupon,CBondContainer::CouponSHIBOR,"SHIBOR");
			AddTypeName(kTypeCategoryCoupon,CBondContainer::CouponDEPO, "DEPO");
			AddTypeName(kTypeCategoryCoupon,CBondContainer::CouponLPR, "LPR");
			AddTypeName(kTypeCategoryCoupon,CBondContainer::CouponFIX,"FIXED");

			AddTypeName(kTypeCategoryInst,CBondContainer::InstNone,"");
			AddTypeName(kTypeCategoryInst,CBondContainer::InstAll,"ALL");
			AddTypeName(kTypeCategoryInst,CBondContainer::InstCentr,"CGE");
			AddTypeName(kTypeCategoryInst,CBondContainer::InstConty,"LGE");
			AddTypeName(kTypeCategoryInst,CBondContainer::InstPrvat,"PVE");
			AddTypeName(kTypeCategoryInst,CBondContainer::InstOther,"OTE");

			AddTypeName(kTypeCategoryRating,CBondContainer::RatingNone,"");
			AddTypeName(kTypeCategoryRating,CBondContainer::RatingAll,"ALL");
			AddTypeName(kTypeCategoryRating,CBondContainer::RatingAAAP,"AAA+");
			AddTypeName(kTypeCategoryRating,CBondContainer::RatingAAA,"AAA");
			AddTypeName(kTypeCategoryRating,CBondContainer::RatingAAP,"AA+");
			AddTypeName(kTypeCategoryRating,CBondContainer::RatingAA,"AA");
			AddTypeName(kTypeCategoryRating,CBondContainer::RatingAAN,"AA-");
			AddTypeName(kTypeCategoryRating,CBondContainer::RatingAP,"A+");
			AddTypeName(kTypeCategoryRating,CBondContainer::RatingOther,"");

			AddTypeName(kTypeCategoryProd,CBondContainer::ProdNone,"");
			AddTypeName(kTypeCategoryProd,CBondContainer::ProdAll,"全部");
			AddTypeName(kTypeCategoryProd,CBondContainer::ProdLocal,"地方债");
			AddTypeName(kTypeCategoryProd,CBondContainer::ProdCountry,"国债");
			AddTypeName(kTypeCategoryProd,CBondContainer::ProdCenter,"央票");
			AddTypeName(kTypeCategoryProd,CBondContainer::ProdFinance,"金融债");
			AddTypeName(kTypeCategoryProd,CBondContainer::ProdShort,"短融");
			AddTypeName(kTypeCategoryProd,CBondContainer::ProdChina,"中票");
			AddTypeName(kTypeCategoryProd,CBondContainer::ProdEnterpr,"企业债");
			AddTypeName(kTypeCategoryProd,CBondContainer::ProdPPN,"PPN");
			AddTypeName(kTypeCategoryProd,CBondContainer::ProdNCD,"NCD");

			AddTypeName(kTypeCategoryCDCRating, CBondContainer::CDCRatingNone,	"");
			AddTypeName(kTypeCategoryCDCRating, CBondContainer::CDCRatingAll,	"ALL");
			AddTypeName(kTypeCategoryCDCRating, CBondContainer::CDCRatingAAAP,	"AAA+");
			AddTypeName(kTypeCategoryCDCRating, CBondContainer::CDCRatingAAA,	"AAA");
			AddTypeName(kTypeCategoryCDCRating, CBondContainer::CDCRatingAAAM,	"AAA-");
			AddTypeName(kTypeCategoryCDCRating, CBondContainer::CDCRatingAAP,	"AA+");
			AddTypeName(kTypeCategoryCDCRating, CBondContainer::CDCRatingAA,	"AA");
			AddTypeName(kTypeCategoryCDCRating, CBondContainer::CDCRatingAA2, "AA(2)");
			AddTypeName(kTypeCategoryCDCRating, CBondContainer::CDCRatingAAM,	"AA-");
			AddTypeName(kTypeCategoryCDCRating, CBondContainer::CDCRatingOther, "");

			AddTypeName(kTypeCategoryCSIRating, CBondContainer::CSIRatingNone,	"");
			AddTypeName(kTypeCategoryCSIRating, CBondContainer::CSIRatingAll,	"ALL");
			AddTypeName(kTypeCategoryCSIRating, CBondContainer::CSIRatingAAAP,	"AAA+");
			AddTypeName(kTypeCategoryCSIRating, CBondContainer::CSIRatingAAA,	"AAA");
			AddTypeName(kTypeCategoryCSIRating, CBondContainer::CSIRatingAAP,	"AA+");
			AddTypeName(kTypeCategoryCSIRating, CBondContainer::CSIRatingAA,	"AA");
			AddTypeName(kTypeCategoryCSIRating, CBondContainer::CSIRatingAA2,	"AA2");
			AddTypeName(kTypeCategoryCSIRating, CBondContainer::CSIRatingAAM,	"AA-");
			AddTypeName(kTypeCategoryCSIRating, CBondContainer::CSIRatingOther, "");

			AddTypeName(kTypeCategoryCBRRating, CBondContainer::CBRRatingNone,	"");
			AddTypeName(kTypeCategoryCBRRating, CBondContainer::CBRRatingAll,	"ALL");
			AddTypeName(kTypeCategoryCBRRating, CBondContainer::CBRRatingAAAP, "AAA+");
			AddTypeName(kTypeCategoryCBRRating, CBondContainer::CBRRatingAAA,	"AAA");
			AddTypeName(kTypeCategoryCBRRating, CBondContainer::CBRRatingAAAM,	"AAA-");
			AddTypeName(kTypeCategoryCBRRating, CBondContainer::CBRRatingAAP,	"AA+");
			AddTypeName(kTypeCategoryCBRRating, CBondContainer::CBRRatingAA,	"AA");
			AddTypeName(kTypeCategoryCBRRating, CBondContainer::CBRRatingAAM,	"AA-");
			AddTypeName(kTypeCategoryCBRRating, CBondContainer::CBRRatingAP,	"A+");			
			AddTypeName(kTypeCategoryCBRRating, CBondContainer::CBRRatingOther, "");

		}
		int  GetCapcity(kTypeCategory category)const
		{
			switch (category)
			{
			case kTypeCategoryCoupon:return CBondContainer::CouponMax + 1; break;
			case kTypeCategoryProd:return CBondContainer::ProdMax + 1; break;
			case kTypeCategoryRating:return CBondContainer::RatingMax + 1; break;
			case kTypeCategoryInst:return CBondContainer::InstMax + 1; break;
			case kTypeCategoryCDCRating:return CBondContainer::CDCRatingMax + 1; break;
			case kTypeCategoryCSIRating:return CBondContainer::CSIRatingMax + 1; break;
			case kTypeCategoryCBRRating:return CBondContainer::CBRRatingMax + 1; break;
				break;
			}
			return 0;
		}
		void AddTypeName(kTypeCategory category, uint32_t nType, const char* name)
		{
			switch (category)
			{
			case kTypeCategoryCoupon:m_coupon_names[nType] = name; break;
			case kTypeCategoryProd:m_prod_names[nType] = name; break;
			case kTypeCategoryRating:m_rating_names[nType] = name; break;
			case kTypeCategoryInst:m_inst_names[nType] = name; break;
			case kTypeCategoryCDCRating:m_cdcrating_names[nType] = name; break;
			case kTypeCategoryCSIRating:m_csirating_names[nType] = name; break;
			case kTypeCategoryCBRRating:m_cbrrating_names[nType] = name; break;
			default:break;
			}
		}
	};

	/*
	大循环
	所有带有大循环的for语句右侧都增加了//BIGLOOP注释
	对于大循环锁,需要以下四个参数:
	开始拿锁的时间
	拿到锁的时间
	释放锁的时间
	代码的名称
	释放锁的时候,其他所有等待此锁的线程的名称,和等待时间
	而且,使用一个宏开关,就可以移除这些功能
	可重入
	*/
}
////////////////////////////////////////////////////////////////////////////////
namespace{
	class ScopedMutex
	{
	public:
		enum kLockType{
			kLockTypeRead,
			kLockTypeWrite,
			kLockTypeHuge
		};
	protected:
		std::recursive_mutex&	m_lock;
		kLockType		m_type;
		uint64_t			m_time_start;
		uint64_t			m_time_get;
		const char*		m_file;
		int				m_line;
	public:
		ScopedMutex(std::recursive_mutex& lock, kLockType type = kLockTypeRead) :m_lock(lock), m_type(type) {
			m_lock.lock();
		}
		ScopedMutex(std::recursive_mutex& lock, const char* file, int line) : m_lock(lock), m_file(file), m_line(line), m_type(kLockTypeHuge) {
			if (m_type == kLockTypeHuge)
				m_time_start = qb::base::HighResTime();
			m_lock.lock();
			if (m_type == kLockTypeHuge)
				m_time_get = qb::base::HighResTime();
		}
		~ScopedMutex() { 
			m_lock.unlock();
			if (m_type == kLockTypeHuge)
			{
				uint64_t curtime = qb::base::HighResTime();
				log_info("[HUGELOCK]time:%8d-%8d  file:%s-%d", (unsigned int)(m_time_get - m_time_start),
					(unsigned int)(curtime - m_time_get), qb::base::StringUtil::GetShortFileName(m_file, 1), m_line);
			}
		}
	};

#define HUGELOCK(LOCK)	ScopedMutex	_scoped_(LOCK,__FILE__,__LINE__);
#define READLOCK(LOCK)	ScopedMutex	_scoped_(LOCK,ScopedMutex::kLockTypeRead);
#define WRITELOCK(LOCK)	ScopedMutex	_scoped_(LOCK,ScopedMutex::kLockTypeWrite);
}

void _SplitStr(std::vector<std::string>& dst, const std::string& src, const std::string& seps)
{
	dst.clear();

	size_t last = 0;
	size_t index = 0;
	int kLen = seps.length();
	index = src.find(seps, 0);
	while (index != std::string::npos)
	{
		if (index - last > 0)
		{
			dst.push_back(src.substr(last, index - last));
		}

		last = index + kLen;
		index = src.find(seps, last);
	}

	if (src.length() > last)
	{
		dst.push_back(src.substr(last));
	}
}

BrokerKey::BrokerKey():m_nIndex(0),m_brokid(""){
};

BrokerKey::BrokerKey(const char* szid, int nIndex):
m_nIndex(nIndex), m_brokid(szid)
{

}
BrokerKey::BrokerKey(BrokerKey&& broker):
m_brokid(std::move(broker.m_brokid)),
m_nIndex(broker.m_nIndex)
{
}
BrokerKey::BrokerKey(const BrokerKey& broker) :
	m_brokid(broker.m_brokid),
	m_nIndex(broker.m_nIndex)
{
}
BrokerKey& BrokerKey::operator = (BrokerKey&& broker){
	std::swap(m_brokid, broker.m_brokid);
	std::swap(m_nIndex, broker.m_nIndex);
	return *this;
}

BrokerKey& BrokerKey::operator = (const BrokerKey& broker) {
	m_brokid = broker.m_brokid;
	m_nIndex = broker.m_nIndex;
	return *this;
}

BrokerKey::BrokerKey(const std::string &szid, int nIndex):
m_nIndex(nIndex),m_brokid(szid)
{

};
unsigned int BrokerKey::GetHash()const{
	unsigned int hash = m_nIndex;
	hash += m_brokid.size()>0?(qb::base::GetFastHash(m_brokid.c_str(),m_brokid.size(), 0)):0;
	return hash;
}
bool BrokerKey::operator == (const BrokerKey& key)const{ return m_nIndex == key.m_nIndex && m_brokid == key.m_brokid; }
const bool BrokerKey::operator < (const BrokerKey& obj) const  
{  
	if (m_brokid < obj.m_brokid)
		return true;
	else if (m_brokid == obj.m_brokid && m_nIndex < obj.m_nIndex)
	{
		return true;
	}
	else
		return false;
}
void BrokerKey::Clear() {
	m_nIndex = 0;
	m_brokid = "";	// 0 对应""
}
void BrokerKey::SetBrokerId(const std::string& brokerIdStr)
{
	m_brokid = brokerIdStr;
}
void BrokerKey::SetBrokerId(const char* brokerIdStr)
{
	m_brokid = brokerIdStr;
}
const std::string& BrokerKey::GetBrokerId()const
{
	return m_brokid;
}
////////////////////////////////////////////////////////////////////////////////

CBondContainer::CBondContainer():
m_map(StringPtrMap::kKeyModeAsCode), 
m_keymap(StringPtrMap::kKeyModeAsKey)
{
	m_nMinIssueDate = -1;
	m_nMaxIssueDate = -1;
	m_pfnProgressProgram = 0;
	m_nLastReportDate = 0;
	m_nLastCalcDate = 0;
	ReserveSize(g_nMaxSize, g_nMaxAddiSize);
}

CBondContainer& CBondContainer::instance()
{
	static CBondContainer s_container;
	return s_container;
}

CBondContainer::~CBondContainer()
{
	//Clear( );
}
void CBondContainer::ReserveSize(int maxBondListSize, int maxAddSize)
{
	HUGELOCK(m_mutex);
	//LOGINFO("m_vctbond size:%d capcity:%d,m_vctaddi size:%d capcity:%d",
		//m_vctbond.size(), m_vctbond.capacity(), m_vctaddi.size(), m_vctaddi.capacity());

	m_vctbond.reserve(maxBondListSize);
	m_vctaddi.reserve(maxAddSize);
	m_vctoptioninfo.reserve(g_nMaxOptionInfoSize);
	m_vctauctioninfo.reserve(g_nMaxAuctionInfoSize);
	int hash_capcity = qb::base::GetHashPrimeLargerThan(maxBondListSize);
	m_map.InitHashTable(hash_capcity);
	m_keymap.InitHashTable(hash_capcity);
	//LOGINFO("reserve:%d,%d  size:%d capcity:%d,m_vctaddi size:%d capcity:%d",
		//maxBondListSize,maxAddSize,
		//m_vctbond.size(), m_vctbond.capacity(), m_vctaddi.size(), m_vctaddi.capacity());
}
void CBondContainer::RebuildMap()
{
	int nCapacity = 0;
	{
		HUGELOCK(m_mutex);
		nCapacity = m_vctbond.capacity();
		SetMap();
	}

	BrokerRepMng->Reserve(nCapacity);
	BankClientRepMng->Reserve(nCapacity);
	BankRepMng->Reserve(nCapacity);
	XCQuoteRepMng->Reserve(nCapacity);
	CfetsRepMng->Reserve(nCapacity);
	CfetsDealRepMng->Reserve(nCapacity);
}

bool CBondContainer::Lock()
{
	m_mutex.lock();
	return true;
}

bool CBondContainer::UnLock()
{
	m_mutex.unlock();
	return true;
}

int CBondContainer::Add( CBondInfo &newElement, CAdditionBondInfo* pAddi, CBondCompanyRep* pCompanyRep, CBondBankRep* pBankRep, CXCQuoteRep *pXCQuote, CCFETSQuoteRep* pCFETSQuote)
{
	return Add(new CBondInfo(newElement), pAddi, pCompanyRep, pBankRep, pXCQuote, pCFETSQuote);
}

int	CBondContainer::Add(CBondInfo* pNewElement, CAdditionBondInfo* pAddi/*=nullptr*/, CBondCompanyRep* pCompanyRep , CBondBankRep* pBankRep , CXCQuoteRep *pXCQuote , CCFETSQuoteRep* pCFETSQuote )
{
	// 使得外部来创建CBondInfo
	WRITELOCK(m_mutex);
	int capcity = m_vctbond.capacity();
	m_vctbond.push_back(pNewElement);
	if (m_vctbond.capacity() != capcity)
	{
		//BLOGCRIT("[BONDS]m_vctbond changed capcity from %d to %d", capcity, m_vctbond.capacity());
	}
	int nIndex = m_vctbond.size() - 1;
	AddAdditionInfo(nIndex, pAddi);
	m_map.SetAt(pNewElement->GetCombBondCode(), (void *)nIndex);
	m_keymap.SetAt(pNewElement->GetCombBondKey(), (void *)nIndex);
	return nIndex;
}
int	CBondContainer::AddAdditionInfo( int nBondIndex, CAdditionBondInfo* pAddInfo)
{
	WRITELOCK(m_mutex);
	if (nBondIndex < 0 || nBondIndex >= (int)m_vctbond.size() || nullptr == pAddInfo)
		return -1;
	int capcity = m_vctaddi.capacity();
	m_vctaddi.push_back(new CAdditionBondInfo(*pAddInfo));
	if (m_vctaddi.capacity() != capcity)
	{
		//BLOGCRIT("[BONDS]m_vctaddi changed capcity from %d to %d",capcity,m_vctaddi.capacity());
	}
	int nAddiIndex = m_vctaddi.size() - 1;

	CBondInfo* pinfo = m_vctbond[nBondIndex];
	if(pinfo){
		pinfo->SetAdditionInfoIndex(nAddiIndex);
	}

	int nFirstIndex = GetBondIndexImpl(pAddInfo->GetFirstIssueKey(),-1);
	m_mapaddi[nFirstIndex].insert(nBondIndex);

	return nBondIndex;
}

int	CBondContainer::AddBondOptionInfo(CBondOptionInfo* pOpi)
{
	WRITELOCK(m_mutex);
	if (nullptr == pOpi)return -1;

	int capcity = m_vctoptioninfo.capacity();
	m_vctoptioninfo.push_back(new CBondOptionInfo(*pOpi));
	if (m_vctoptioninfo.capacity() != capcity)
	{
		//BLOGCRIT("[BONDS]m_vctoptioninfo changed capcity from %d to %d", capcity, m_vctoptioninfo.capacity());
	}
	int nIndex = m_vctoptioninfo.size() - 1;
	int bondIndex = GetBondIndex(pOpi->GetCombBondKey());
	if (!IsValidIndex(bondIndex))return nIndex;
	
	CBondInfo* pinfo = m_vctbond[bondIndex];
	if (pinfo){
		pinfo->SetOptionInfoIndex(nIndex);
	}

	return nIndex;
}

void CBondContainer::RemoveBondOptionInfo(CBondOptionInfo* pOpi)
{
	WRITELOCK(m_mutex);
	if (nullptr == pOpi)return;

	int bondIndex = GetBondIndex(pOpi->GetCombBondKey());
	if (!IsValidIndex(bondIndex))return;

	CBondInfo* pinfo = m_vctbond[bondIndex];
	if (!pinfo)return;
	
	int nIndex = pinfo->GetOptionInfoIndex();
	if (nIndex < 0 || nIndex >= m_vctoptioninfo.size())return;
	CBondOptionInfo* opi = m_vctoptioninfo[nIndex];
	if (!opi)return;
	if (strcmp(opi->GetCombBondKey(), pinfo->GetCombBondKey()) != 0)return;
	delete opi;
	m_vctoptioninfo[nIndex] = nullptr;
	return;
}

const CBondOptionInfo* CBondContainer::GetBondOptionInfo(int index) const
{
	if (index < 0 || index >= m_vctoptioninfo.size())return nullptr;

	return m_vctoptioninfo[index];
}

int	CBondContainer::AddBondAuctionInfo(int nBondIndex, CBondAuctionInfo* pAuc)
{
	WRITELOCK(m_mutex);
	if (nBondIndex<-1 || nBondIndex >= (int)m_vctbond.size() || nullptr == pAuc)
		return -1;

	if (nBondIndex == -1)
	{//Auction字典比Bond字典早更新的情况
		static CBondInfo biEmpty;
		biEmpty.Clear();
		biEmpty.SetListedMarket(pAuc->GetBondKey());
		biEmpty.SetBondKey(pAuc->GetBondKey());
		nBondIndex = Add(biEmpty, nullptr);
	}

	int capcity = m_vctauctioninfo.capacity();
	m_vctauctioninfo.push_back(new CBondAuctionInfo(*pAuc));
	if (m_vctauctioninfo.capacity() != capcity)
	{
		//BLOGCRIT("[BONDS]m_vctauctioninfo changed capcity from %d to %d", capcity, m_vctauctioninfo.capacity());
	}
	int nIndex = m_vctauctioninfo.size() - 1;

	m_mapauctioninfo[nBondIndex] = nIndex;
	return nBondIndex;
}

void CBondContainer::RemoveBondAuctionInfo(int nBondIndex)
{
	WRITELOCK(m_mutex);
	auto it = m_mapauctioninfo.find(nBondIndex);
	if (it == m_mapauctioninfo.end())return;

	int nIndex = it->second;
	if (nIndex < 0 || nIndex >= m_vctauctioninfo.size())return;
	CBondAuctionInfo* opi = m_vctauctioninfo[nIndex];
	if (!opi)return;
	delete opi;
	m_vctauctioninfo[nIndex] = nullptr;
	return;
}

const CBondAuctionInfo* CBondContainer::GetBondAuctionInfo(int nBondIndex)
{
	auto it = m_mapauctioninfo.find(nBondIndex);
	if (it == m_mapauctioninfo.end())return nullptr;
	return m_vctauctioninfo[it->second];
}

int	CBondContainer::AddABSBondInfo(int nBondIndex, CABSBondInfo* pInfo)
{
	////WRITELOCK(m_mutex);
	if (nBondIndex < 0 || nBondIndex >= (int)m_vctbond.size() || nullptr == pInfo)
		return -1;
	
	int capcity = m_vctabsbond.capacity();
	m_vctabsbond.push_back(new CABSBondInfo(*pInfo));
	if (m_vctabsbond.capacity() != capcity)
	{
		//BLOGCRIT("[BONDS]m_vctabsbond changed capcity from %d to %d", capcity, m_vctabsbond.capacity());
	}
	int nIndex = m_vctabsbond.size() - 1;

	m_mapabsbond[nBondIndex] = nIndex;
	
	return nBondIndex;
}

const CABSBondInfo* CBondContainer::GetABSBondInfo(int nBondIndex)
{
	auto it = m_mapabsbond.find(nBondIndex);
	if (it == m_mapabsbond.end())return nullptr;
	return m_vctabsbond[it->second];
}

int CBondContainer::GetMatchType(const char* pstr)
{
	int nRet = -1;
	char* pt = (char*)pstr;
	char nChar = pt[0];
	while(nChar!='\0')
	{
		if(nChar>='0' && nChar<='9')
		{
			if(nRet>0 && nRet!=1)
			{
				nRet = 3;
				break;
			}
			nRet = 1;
		}
		else if(nChar>='A' && nChar<='Z')
		{
			if(nRet>0 && nRet!=2)
			{
				nRet = 3;
				break;
			}
			nRet = 2;
		}
		else
		{
			nRet = 3;
			break;
		}
		pt++;
		nChar = pt[0];
	}

	return nRet;
}

bool CBondContainer::GetBondClntPrice(const BLHCONDITION & Cond, int nID )
{
	if( nID<0 || nID>=instance().GetSize())
		return false;

	BKQUOTE quote = { 0 };
	if (instance().GetClentInfoById(Cond.sCompanyid, nID,quote))
	{
		BKQUOTE *pRep = &quote;
		if(pRep->m_Freeze == 1) 
			return false;

		if( strcmp(pRep->m_BidStatus,"1")!=0 && strcmp(pRep->m_OfrStatus,"1")!=0)
			return false;//双边无报价
		if( atof(pRep->m_BidVol)==0.0 &&  atof(pRep->m_OfrVol)==0.0) 
			return false;//双边量为0

		//价、量只要一边为0即表示无交，如果两边都不效则不显示
		if ((atof(pRep->m_Bid)<=0.0000 || atof(pRep->m_BidVol)<=0.0000) &&
			(atof(pRep->m_Ofr)<=0.0000 || atof(pRep->m_OfrVol)<=0.0000))
		{
			return false;
		}

		return ( (!IsEmpty(pRep->m_Bid) && strcmp(pRep->m_BidStatus,"1")==0) || 
			(!IsEmpty(pRep->m_Ofr) && strcmp(pRep->m_OfrStatus,"1")==0));//有效报价
	}
	return false;
}

bool CBondContainer::IsHasPriceEx(const BLHCONDITION & Cond, int nID, bool bAttion)
{
	if (Cond.nBnkFlg == 1)			//	nBnkFlg    0=现券报价（二级）， 1=银行报价， 2=海外版中间价
		return GetBondBkPrice(Cond, nID);


	if (IsEmpty(Cond.sCompanyid))	// 经纪公司ID，银行ID
	{
		if (nID < 0 || nID >= GetSize())
			return false;
		CBondCompanyRep* ptmp = GetCompanyRep(nID);
		if (ptmp && ptmp->GetSize()>0)
			return ptmp->IsHasPrice("", Cond.nBnkFlg);
		return false;
	}
	CBondCompanyRep* ptmp = GetCompanyRep(nID);
	if (ptmp)
		return ptmp->IsHasPrice(Cond.sCompanyid, Cond.nBnkFlg);

	return false;
}

bool CBondContainer::IsHasPrice(const BLHCONDITION & Cond, int nID, bool bAttion)
{
	if( Cond.nBnkFlg == 1 )
		return GetBondBkPrice( Cond, nID );

	if( IsEmpty(Cond.sCompanyid) )
	{
		if( nID<0 || nID>=instance().GetSize())
			return false;

		
		CBondCompanyRep* ptmp = instance().GetCompanyRep(nID);
		if(ptmp && ptmp->GetSize()>0)
			return instance().GetCompanyInfoById(nID);
		return false;
		
	}
	REPORT quote={0};
	if(instance().GetCompanyInfoById(Cond.sCompanyid,nID,quote))
	{
		REPORT* pRep=&quote;
		if(Cond.nBnkFlg == 2)
		{
			return (!IsEmpty(pRep->m_indx_info.m_price) );
		}
		else
		{
			if( strcmp(pRep->m_bidinfo.m_price_status,"0")==0 && strcmp(pRep->m_askinfo.m_price_status,"0")==0)
				return false;
			if((atoi(pRep->m_bidinfo.m_rebate)==1 && strcmp(pRep->m_bidinfo.m_price_status,"0")!=0) || 
				(atoi(pRep->m_askinfo.m_rebate)==1 && strcmp(pRep->m_askinfo.m_price_status,"0")!=0))
				return true;
			return ( (!IsEmpty(pRep->m_bidinfo.m_sPrice) && strcmp(pRep->m_bidinfo.m_price_status,"0")!=0) || 
				(!IsEmpty(pRep->m_askinfo.m_sPrice) && strcmp(pRep->m_askinfo.m_price_status,"0")!=0));
		}

	}
	return false;
}

bool CBondContainer::GetCFETSBidCndPrice(const BLHCONDITION & Cond, int nID)
{
	if (nID < 0 || nID >= instance().GetSize())
		return false;

	if (IsEmpty(Cond.sBPrice) && IsEmpty(Cond.sBPriceEnd))
		return true;

	
	CCFETSQuoteRep* rep = instance().GetCFETSQuote(nID);
	if (rep)
	{
		CFETSQUOTE quote;
		if (!rep->GetQuoteByKey((CCFETSQuote::CFETSQUOTETYPE)Cond.nCFETSQuoteType, quote))
			return false;

		if (!IsEmpty(quote.m_BidPriceYield))
		{
			float fBid = atof(quote.m_BidPriceYield);

			bool bRet = false;
			if (!IsEmpty(Cond.sBPrice) && !IsEmpty(Cond.sBPriceEnd))
			{
				bRet = (fBid > (atof(Cond.sBPrice) - 0.00001));
				if (bRet)
					bRet = (fBid < (atof(Cond.sBPriceEnd) + 0.00001));
			}
			else
			{
				if (!IsEmpty(Cond.sBPrice))
					bRet = (fBid > (atof(Cond.sBPrice) - 0.00001));

				if (!bRet && !IsEmpty(Cond.sBPriceEnd))
					bRet = (fBid < (atof(Cond.sBPriceEnd) + 0.00001));
			}

			return bRet;
		}
	}
	
    return false;
}

bool CBondContainer::GetCFETSOfrCndPrice(const BLHCONDITION & Cond, int nID)
{
	if (nID < 0 || nID >= instance().GetSize())
		return false;

	if (IsEmpty(Cond.sOPrice) && IsEmpty(Cond.sOPriceEnd))
		return true;

	
	CCFETSQuoteRep* rep = instance().GetCFETSQuote(nID);
	if (rep)
	{
		CFETSQUOTE quote;
		if (!rep->GetQuoteByKey((CCFETSQuote::CFETSQUOTETYPE)Cond.nCFETSQuoteType, quote))
			return false;
		
		if (!IsEmpty(quote.m_OfrPriceYield))
		{
			float fOfr = atof(quote.m_OfrPriceYield);

			bool bRet = false;
			if (!IsEmpty(Cond.sOPrice) && !IsEmpty(Cond.sOPriceEnd))
			{
				bRet = (fOfr > (atof(Cond.sOPrice) - 0.00001));
				if (bRet)
					bRet = (fOfr < (atof(Cond.sOPriceEnd) + 0.00001));
			}
			else
			{
				if (!IsEmpty(Cond.sOPrice))
					bRet = (fOfr > (atof(Cond.sOPrice) - 0.00001));

				if (!bRet && !IsEmpty(Cond.sOPriceEnd))
					bRet = (fOfr < (atof(Cond.sOPriceEnd) + 0.00001));
			}

			return bRet;
		}
	}
	
	return false;
}


bool CBondContainer::GetCFETSBidCdcCompare(const BLHCONDITION & Cond, int nID, bool bIsCDCAuthValid)
{
	if (Cond.sBidCdc[0] == '\0' && Cond.sBidCdcEnd[0] == '\0')return true;

	CCFETSQuoteRep* rep = CBondContainer::instance().GetCFETSQuote(nID);
	if (!rep)return false;

	CFETSQUOTE quote;
	if (!rep->GetQuoteByKey((CCFETSQuote::CFETSQUOTETYPE)Cond.nCFETSQuoteType, quote))return false;

	if (quote.m_BidPriceYield[0] == '\0' || strcmp(quote.m_BidPriceYield, "0") == 0) return false;

	double dDiff = CBondCDCPriceInfo::instance().GetYesterdayCDCPriceGap(bIsCDCAuthValid, nID, CBondCDCPriceInfo::price_type_yield, true, quote.m_BidPriceYield, INVALID_CDC_VALUE, false);
	if (dDiff < INVALID_CDC_VALUE + 1e-6)return false	;
	if (Cond.sBidCdc[0] != 0)
	{
		if (dDiff < atof(Cond.sBidCdc) - 1e-6)
			return false;
	}
	if (Cond.sBidCdcEnd[0] != 0)
	{
		if (dDiff > atof(Cond.sBidCdcEnd) + 1e-6)
			return false;
	}
	return true;
}

bool CBondContainer::GetCFETSCdcOfrCompare(const BLHCONDITION & Cond, int nID, bool bIsCDCAuthValid)
{
	if (Cond.sCdcOfr[0] == '\0' && Cond.sCdcOfrEnd[0] == '\0')return true;

	CCFETSQuoteRep* rep = CBondContainer::instance().GetCFETSQuote(nID);
	if (!rep)return false;

	CFETSQUOTE quote;
	if (!rep->GetQuoteByKey((CCFETSQuote::CFETSQUOTETYPE)Cond.nCFETSQuoteType, quote))return false;

	if (quote.m_OfrPriceYield[0] == '\0' || strcmp(quote.m_OfrPriceYield, "0") == 0) return false;
	double dDiff = CBondCDCPriceInfo::instance().GetYesterdayCDCPriceGap(bIsCDCAuthValid, nID, CBondCDCPriceInfo::price_type_yield, false, quote.m_OfrPriceYield, INVALID_CDC_VALUE, false);
	if (dDiff < INVALID_CDC_VALUE + 1e-6)return false;
	if (Cond.sCdcOfr[0] != 0)
	{
		if (dDiff < atof(Cond.sCdcOfr) - 1e-6)
			return false;
	}
	if (Cond.sCdcOfrEnd[0] != 0)
	{
		if (dDiff > atof(Cond.sCdcOfrEnd) + 1e-6)
			return false;
	}
	return true;
}

bool CBondContainer::GetCFETSDiffPrice(const BLHCONDITION & Cond, int nID)
{
	if (nID < 0 || nID >= instance().GetSize())return false;
	float fDiffprc = atof(Cond.sDiffPrice);

	CCFETSQuoteRep* rep = instance().GetCFETSQuote(nID);
	if (rep){
		CFETSQUOTE quote;
		if (!rep->GetQuoteByKey((CCFETSQuote::CFETSQUOTETYPE)Cond.nCFETSQuoteType, quote))return false;
		if (!IsEmpty(quote.m_BidPriceYield)){
			return fDiffprc >= (atof(quote.m_BidPriceYield) - atof(quote.m_OfrPriceYield))*100.00;
		}
	}

	return false;
}

bool CBondContainer::GetCFETSBidVol(const BLHCONDITION& Cond, int nID)
{
	if (!IsValidIndex(nID))return false;
	if (IsEmpty(Cond.sVolBid))return true;

	double fFilterVol = atof(Cond.sVolBid);

	CCFETSQuoteRep* rep = instance().GetCFETSQuote(nID);
	if (rep) {
		CFETSQUOTE quote;
		if (!rep->GetQuoteByKey((CCFETSQuote::CFETSQUOTETYPE)Cond.nCFETSQuoteType, quote))return false;
		if (IsEmpty(quote.m_BidVol))return false;
		double fVolumn = atof(quote.m_BidVol);
		if (Cond.nVolBpcCnd == 0 && fVolumn < fFilterVol + 0.000001) //0 表示[<= ], 1 表示[>= ]
		{
			return true;
		}
		else if(Cond.nVolBpcCnd==1 && fVolumn > fFilterVol - 0.000001)
		{
			return true;
		}
	}

	return false;
}

bool CBondContainer::GetCFETSOfrVol(const BLHCONDITION& Cond, int nID)
{
	if (!IsValidIndex(nID))return false;
	if (IsEmpty(Cond.sVolOfr))return true;
	
	double fFilterVol = atof(Cond.sVolOfr);

	CCFETSQuoteRep* rep = instance().GetCFETSQuote(nID);
	if (rep) {
		CFETSQUOTE quote;
		if (!rep->GetQuoteByKey((CCFETSQuote::CFETSQUOTETYPE)Cond.nCFETSQuoteType, quote))return false;
		if (IsEmpty(quote.m_OfrVol))return false;
		double fVolumn = atof(quote.m_OfrVol);
		if (Cond.nVolOpcCnd == 0 && fVolumn < fFilterVol + 0.000001) //0 表示[<= ], 1 表示[>= ]
		{
			return true;
		}
		else if (Cond.nVolOpcCnd == 1 && fVolumn > fFilterVol - 0.000001)
		{
			return true;
		}
	}

	return false;
}

bool CBondContainer::IsCFETSBilateralPrice(const BLHCONDITION & Cond, int nID)
{//CFETS双边报价检查
	if (strcmp(Cond.sCompanyid, "50") != 0)return false;
	
	CCFETSQuoteRep* rep = instance().GetCFETSQuote(nID);
	if (!rep)return false;
	CFETSQUOTE quote;
	if (!rep->GetQuoteByKey((CCFETSQuote::CFETSQUOTETYPE)Cond.nCFETSQuoteType, quote))return false;
	return ((!IsEmpty(quote.m_BidPriceYield) || !IsEmpty(quote.m_BidPriceClean) || !IsEmpty(quote.m_BidVol))
		&& (!IsEmpty(quote.m_OfrPriceYield) || !IsEmpty(quote.m_OfrPriceClean) || !IsEmpty(quote.m_OfrVol)));

	return true;
}

bool CBondContainer::IsCFETSHasPrice(const BLHCONDITION & Cond, int nID)
{
	if (strcmp(Cond.sCompanyid, "50") != 0)return false;
	
	CCFETSQuoteRep* rep = instance().GetCFETSQuote(nID);
	if (!rep)return false;
	CFETSQUOTE quote;
	if (!rep->GetQuoteByKey((CCFETSQuote::CFETSQUOTETYPE)Cond.nCFETSQuoteType, quote))return false;
	return (!IsEmpty(quote.m_BidPriceYield) || !IsEmpty(quote.m_BidPriceClean) || !IsEmpty(quote.m_BidVol)
		|| !IsEmpty(quote.m_OfrPriceYield) || !IsEmpty(quote.m_OfrPriceClean) || !IsEmpty(quote.m_OfrVol));
	
	return false;
}

bool CBondContainer::CheckCFETSSettlement(const BLHCONDITION& Cond, int nID)
{
	if (strcmp(Cond.sCompanyid, "50") != 0)return false;
	
	CCFETSQuoteRep* rep = instance().GetCFETSQuote(nID);
	if (!rep)return false;
	CFETSQUOTE quote;
	if (!rep->GetQuoteByKey((CCFETSQuote::CFETSQUOTETYPE)Cond.nCFETSQuoteType, quote))return false;
	return FilterQuoteByClearSpeed(quote, Cond.nSettlement[0] - 1);
	
	return true;
}

bool CBondContainer::IsCpicHasPrice(const BLHCONDITION & Cond, int nID,bool bBuyPool )
{
	return GetCpicCompanyInfoById(nID,bBuyPool);
}

bool CBondContainer::GetMaturityBond(const CBondInfo & Info )
{
	if(IsEmpty(Info.GetMaturityDate()))
		return false;
	time_t t = ServerTimeMgr::instance().serverTime();
	Info.GetRemainPeriod(t);
	if(strcmp(Info.GetRemainDate(), strBondLib_Expired()/*"已到期"*/)!=0)
		return false;
	return true;
}

bool CBondContainer::GetRebateBond(const CBondInfo & Info)
{
	if(Info.IsRebated())return false;
	return true;
}

bool CBondContainer::GetProdMultiType(const BLHCONDITION & Cond,const CBondInfo & Info )
{
	for( int i=0; i<BLH_BONDTYPECOUNT; i++)
	{
		if(Cond.nType[i]==CBondContainer::BondNone)
			return false;
		const CSPString& strProdType = GetProdType(Cond.nType[i]);
		if(strcmp(strProdType.c_str(), Info.GetBondSubType())==0)
			return true;
		else continue;
	}
	return true;
}

bool CBondContainer::GetSOEenterType(const BLHCONDITION & Cond, const CBondInfo & Info)
{
	int nSize = sizeof(Cond.nType)/sizeof(uint32_t);
	
	for( int i=0; i<nSize; i++)
	{
		if(Cond.nType[i]==0x00)
			return false;
		if(Cond.nType[i]==typeAll)
		{
			CSPString strProdType = Info.GetBondSubType();
			if(!Info.IsSOEenterType() && 
				(strcmp(strProdType.c_str(), GetProdType(ProdShort).c_str())==0 ||
				strcmp(strProdType.c_str(), GetProdType(ProdChina).c_str())==0 ||
				strcmp(strProdType.c_str(), GetProdType(ProdEnterpr).c_str())==0 ||
				strcmp(strProdType.c_str(), GetProdType(ProdPPN).c_str())==0))
			{
				return false;
			}
			return true;
		}
		else if(Cond.nType[i]==ProdShort || Cond.nType[i]==ProdChina || 
			Cond.nType[i]==ProdEnterpr || Cond.nType[i]==ProdPPN)
		{
			CSPString strProdType = GetProdType(Cond.nType[i]);
			if(Info.IsSOEenterType()&&strcmp(strProdType.c_str(),Info.GetBondSubType())==0)
				return true;
			else continue;
		}
		else{
			CSPString strProdType = GetProdType(Cond.nType[i]);
			if(strcmp(strProdType.c_str(),Info.GetBondSubType())==0)
				return true;
			else continue;
		}
	}
	
	return true;
}

bool CBondContainer::GetMultiLevel(const BLHCONDITION & Cond, const CBondInfo & Info)
{
	// 非ALL情况下对指定债券的主体评级与过滤器值进行对比
	// 
	CBondContainer::IssuerRating filter = CBondContainer::RatingNone;
	int nSize = sizeof(Cond.nIssuerRating)/sizeof(uint32_t);
	for( int i=0; i<nSize; i++)
	{
		if(Cond.nIssuerRating[i]==0x00)
			return false;
		filter = (CBondContainer::IssuerRating)Cond.nIssuerRating[i];
		if (filter == CBondContainer::RatingOther)
		{
			if (strcmp(Info.GetBondSubType(), "PSB") == 0)
				return false;

			if (TypeNameManager::Get().IsRatingEqual(filter, Info.GetIssuerRating()) &&
				TypeNameManager::Get().IsRatingEqual(filter, Info.GetInstitutionRating()))
				return true;
		}
		else
		{
			if (TypeNameManager::Get().IsRatingEqual(filter, Info.GetIssuerRating()))
				return true;
			if (TypeNameManager::Get().IsRatingEqual(filter, Info.GetInstitutionRating()))
				return true;
		}
	}
	return false;
}

bool CBondContainer::GetCDCRatingLevel(const BLHCONDITION & Cond, const CBondInfo &Info)
{
	if (!SSUserAccountManager::instance().HasAuthOfCDC())
		return true;

	CBondContainer::CDCRating filter = CBondContainer::CDCRatingNone;
	int nSize = sizeof(Cond.nCDCRating) / sizeof(uint32_t);
	for (int i = 0; i < nSize; i++)
	{
		if (Cond.nCDCRating[i] == 0x00)
			return false;
		filter = (CBondContainer::CDCRating)Cond.nCDCRating[i];
		if (TypeNameManager::Get().IsCDCRatingEqual(filter, Info.GetCDCRating()))
			return true;
	}

	return false;
}

bool CBondContainer::GetCSIRatingLevel(const BLHCONDITION & Cond, const CBondInfo &Info)
{
	if (!SSUserAccountManager::instance().HasAuthOfCSI())
		return true;

	{
		CBondContainer::CSIRating filter = CBondContainer::CSIRatingNone;
		int nSize = sizeof(Cond.nCSIRating) / sizeof(uint32_t);
		for (int i = 0; i < nSize; i++)
		{
			if (Cond.nCSIRating[i] == 0x00)
				return false;
			filter = (CBondContainer::CSIRating)Cond.nCSIRating[i];
			if (TypeNameManager::Get().IsCSIRatingEqual(filter, Info.GetCSIRating()))
				return true;
		}
	}

	return false;
}

bool CBondContainer::GetCBRRatingLevel(const BLHCONDITION & Cond, const CBondInfo &Info)
{
	if (!SSUserAccountManager::instance().HasAuthOfCBR())
		return true;

	{
		CBondContainer::CBRRating filter = CBondContainer::CBRRatingNone;
		int nSize = sizeof(Cond.nCBRRating) / sizeof(uint32_t);
		for (int i = 0; i < nSize; i++)
		{
			if (Cond.nCBRRating[i] == 0x00)
				return false;
			filter = (CBondContainer::CBRRating)Cond.nCBRRating[i];
			if (TypeNameManager::Get().IsCBRRatingEqual(filter, Info.GetCBRRating()))
				return true;
		}
	}

	return false;
}

bool CBondContainer::GetOutlookRatingLevel(const BLHCONDITION & Cond, const CBondInfo &Info)
{
	CBondContainer::OutlookRating filter = OutlookRatingNone;
	int nSize = sizeof(Cond.nOutlookRating) / sizeof(uint32_t);
	for (int i = 0; i < nSize; ++i)
	{
		if (Cond.nOutlookRating[i] == OutlookRatingNone)
			return false;
		filter = (CBondContainer::OutlookRating)Cond.nOutlookRating[i];
		CBondContainer::OutlookRating nBondOutlookRating = OutlookRatingNone;
		if (strcmp(Info.GetOutlook(), "STB") == 0)
		{
			nBondOutlookRating = CBondContainer::OutlookRatingSTB;
		}
		else if (strcmp(Info.GetOutlook(), "NEG") == 0)
		{
			nBondOutlookRating = CBondContainer::OutlookRatingNEG;
		}
		else if (strcmp(Info.GetOutlook(), "RWT") == 0)
		{
			nBondOutlookRating = CBondContainer::OutlookRatingRWT;
		}
		else if (strcmp(Info.GetOutlook(), "POS") == 0)
		{
			nBondOutlookRating = CBondContainer::OutlookRatingPOS;
		}

		if (nBondOutlookRating == filter)
			return true;
	}

	return false;
}

bool CBondContainer::GetBondBkPrice(const  BLHCONDITION & Cond, int nID)
{
	if( nID<0 || nID>=instance().GetSize())
		return false;

	if( Cond.nBkClnt!=0 )
		return GetBondClntPrice( Cond, nID );

	BKQUOTE quote={0};
	if(instance().GetBankInfoById(Cond.sCompanyid,nID,quote))
	{
		BKQUOTE* pRep=&quote;
		if( strcmp(pRep->m_BidStatus,"1")!=0 && strcmp(pRep->m_OfrStatus,"1")!=0)return false;//双边无报价
		return ( (!IsEmpty(pRep->m_Bid) && strcmp(pRep->m_BidStatus,"1")==0) || 
			(!IsEmpty(pRep->m_Ofr) && strcmp(pRep->m_OfrStatus,"1")==0));//有效报价
	}
	return false;
}
 
bool CBondContainer::GetBondBkdbPrice(const BLHCONDITION & Cond, int nID )
{
	if( nID<0 || nID>=instance().GetSize())
		return false;

	if( Cond.nBkClnt!=0 )
		return GetBondClntdbPrice( Cond, nID );

	BKQUOTE quote={0};
	if(instance().GetBankInfoById(Cond.sCompanyid,nID,quote))
	{
		BKQUOTE* pRep=&quote;
		return ( (!IsEmpty(pRep->m_Bid) && strcmp(pRep->m_BidStatus,"1")==0) && 
				(!IsEmpty(pRep->m_Ofr) && strcmp(pRep->m_OfrStatus,"1")==0));//双边有效报价
	}
	return false;
}

bool CBondContainer::GetMultiCouponType(const BLHCONDITION & Cond, const CBondInfo & Info)
{
	int nSize = sizeof(Cond.nCouponType)/sizeof(uint32_t);
	for( int i=0; i<nSize; i++)
	{
		if(Cond.nCouponType[i]==CouponNon)
			return false;
		CSPString strSpec = GetCouponType(Cond.nCouponType[i]);
		if(strcmp(strSpec.c_str(), Info.GetRateType())==0)
			return true;
	}
	return true;
}

bool CBondContainer::GetMultiInstion(const BLHCONDITION & Cond, const CBondInfo & Info)
{
	int nSize = sizeof(Cond.nInstion)/sizeof(uint32_t);
	for( int i=0; i<nSize; i++)
	{
		if(Cond.nInstion[i]==0x00)
			return false;
		CSPString strInst = GetInstType(Cond.nInstion[i]);
		if(strcmp(strInst.c_str(), Info.GetInstitutionType())==0)
			return true;
		else continue;
	}
	return true;
}

long CBondContainer::GetDateRange(const CBondInfo & Info )
{
	if (IsEmpty(Info.GetMaturityDate()))return 0;

	long lDate = atol(Info.GetMaturityDate());
	int	nYear, nMonth, nDay;
	nYear = lDate/10000;
	nMonth = (lDate%10000)/100;
	nDay = lDate%100;

	QDateTime tmMaturiy(QDate(nYear, nMonth, nDay));
	QDateTime tmNow = QDateTime::fromSecsSinceEpoch(ServerTimeMgr::instance().serverTime());//TODO utc?
	return tmNow.daysTo(tmMaturiy);
}
bool CBondContainer::IsBilateralPrice(const BLHCONDITION & Cond, int nID, bool bAttion )
{//双边报价检查
	if (bAttion){
		REPORT quote = { 0 };
		if (instance().GetCompanyRepByIdEx(nID,Cond.sCompanyid, quote, 2))
		{
			REPORT* pRep = &quote;
			if (strcmp(pRep->m_bidinfo.m_price_status, "0") == 0 || strcmp(pRep->m_askinfo.m_price_status, "0") == 0)	return false;
			if (pRep->m_price_sel != Indicative_Price){
				return (!IsEmpty(pRep->m_bidinfo.m_sPrice) && !IsEmpty(pRep->m_askinfo.m_sPrice));
			}
			else return false;
		}
		return false;
	}
	switch(Cond.nBnkFlg){
		case 0:
			if( IsEmpty(Cond.sCompanyid) )
			{
				return instance().GetBilateralfoById(nID);
			}
			else{
				return instance().IsBilateralfoById(Cond.sCompanyid, nID);

			}
			break;
		case 1:
			return GetBondBkdbPrice( Cond, nID );
			break;
		case 2:
			if( IsEmpty(Cond.sCompanyid) )
			{
				return instance().GetBilateralfoByIdOverSea(nID);
			}
			else{
				REPORT quote = { 0 };
				if (instance().GetCompanyInfoById(Cond.sCompanyid, nID,quote))
				{
					REPORT *pRep = &quote;
					return (strcmp(pRep->m_indx_info.m_symbol, "0") == 0 && !IsEmpty(pRep->m_indx_info.m_price));
				}
				else
					return false;
			}
			break;
		default:
			break;
	}
	return false;
}

bool CBondContainer::GetDiffPrice(const BLHCONDITION & Cond, int nID )
{
	if (IsEmpty(Cond.sCompanyid))
	{
		if (nID < 0 || nID >= instance().GetSize())
			return true;

		CBondCompanyRep* ptmp = instance().GetCompanyRep(nID);
		if (ptmp && ptmp->GetSize()>0)
			return instance().GetDiffenceById(Cond, nID);

		return true;
	}
	float fDiffprc = atof(Cond.sDiffPrice);
	if (Cond.nBnkFlg != 0)
	{
		if (Cond.nBkClnt != 0)
		{
			BKQUOTE quote = { 0 };
			if (instance().GetClentInfoById(Cond.sCompanyid, nID, quote))
			{
				BKQUOTE* pRep = &quote;
				if (strcmp(pRep->m_BidStatus, "1") != 0 || strcmp(pRep->m_OfrStatus, "1") != 0)
					return false;

				if (IsEmpty(pRep->m_Bid) || IsEmpty(pRep->m_Ofr))
					return false;//单边无报价

				return fDiffprc >= (atof(pRep->m_Bid) - atof(pRep->m_Ofr))*100.00;
			}
			return false;
		}
		else
		{
			BKQUOTE quote = { 0 };
			if (instance().GetBankInfoById(Cond.sCompanyid, nID, quote))
			{
				BKQUOTE* pRep = &quote;
				if (strcmp(pRep->m_BidStatus, "1") != 0 || strcmp(pRep->m_OfrStatus, "1") != 0)
					return false;

				if (IsEmpty(pRep->m_Bid) || IsEmpty(pRep->m_Ofr))
					return false;//单边无报价

				return fDiffprc >= (atof(pRep->m_Bid) - atof(pRep->m_Ofr))*100.00;
			}
			return false;
		}
	}
	else
	{
		REPORT quote = { 0 };
		if (instance().GetCompanyInfoById(Cond.sCompanyid, nID, quote))
		{
			REPORT* pRep = &quote;
			if (strcmp(pRep->m_bidinfo.m_sPrice, "Bid") == 0 || strcmp(pRep->m_askinfo.m_sPrice, "Ofr") == 0)
				return false;

			return fDiffprc >= (atof(pRep->m_bidinfo.m_sPrice) - atof(pRep->m_askinfo.m_sPrice))*100.00;
		}
		return false;
	}
	return false;
}

bool CBondContainer::GetBidCndPrice(const BLHCONDITION & Cond, int nID)
{
	if (nID < 0 || nID >= instance().GetSize())
		return false;

	if (IsEmpty(Cond.sBPrice) && IsEmpty(Cond.sBPriceEnd))
		return true;

	if (Cond.nBnkFlg != 0)
	{
		if (Cond.nBkClnt != 0)
		{
			BKQUOTE quote = { 0 };
			if (instance().GetClentInfoById(Cond.sCompanyid, nID, quote))
			{
				BKQUOTE* pRep = &quote;
				if (strcmp(pRep->m_BidStatus, "1") == 0 && !IsEmpty(pRep->m_Bid))
				{
					float fBid = atof(pRep->m_Bid);

					bool bRet = false;
					if (!IsEmpty(Cond.sBPrice) && !IsEmpty(Cond.sBPriceEnd))
					{
						bRet = (fBid > (atof(Cond.sBPrice) - 0.00001));
						if (bRet)
							bRet = (fBid < (atof(Cond.sBPriceEnd) + 0.00001));
					}
					else
					{
						if (!IsEmpty(Cond.sBPrice))
							bRet = (fBid > (atof(Cond.sBPrice) - 0.00001));

						if (!bRet && !IsEmpty(Cond.sBPriceEnd))
							bRet = (fBid < (atof(Cond.sBPriceEnd) + 0.00001));
					}

					return bRet;
				}
			}
			return false;
		}
		else
		{
			return false;
		}
	}
	else
	{
		return instance().GetCompanyBidInfoById(Cond, nID);
	}

	return false;
}

bool CBondContainer::GetOfrCndPrice(const BLHCONDITION & Cond, int nID)
{
	if (nID < 0 || nID >= instance().GetSize())
		return false;

	if (IsEmpty(Cond.sOPrice) && IsEmpty(Cond.sOPriceEnd))
		return true;
		
	if (Cond.nBnkFlg != 0)
	{
		if (Cond.nBkClnt != 0)
		{
			BKQUOTE quote = { 0 };
			if (instance().GetClentInfoById(Cond.sCompanyid, nID, quote))
			{
				BKQUOTE* pRep = &quote;
				if (strcmp(pRep->m_OfrStatus, "1") == 0 && !IsEmpty(pRep->m_Ofr))
				{
					float fOfr = atof(pRep->m_Bid);

					bool bRet = false;
					if (!IsEmpty(Cond.sOPrice) && !IsEmpty(Cond.sOPriceEnd))
					{
						bRet = (fOfr > (atof(Cond.sOPrice) - 0.00001));
						if (bRet)
							bRet = (fOfr < (atof(Cond.sOPriceEnd) + 0.00001));
					}
					else
					{
						if (!IsEmpty(Cond.sOPrice))
							bRet = (fOfr > (atof(Cond.sOPrice) - 0.00001));

						if (!bRet && !IsEmpty(Cond.sOPriceEnd))
							bRet = (fOfr < (atof(Cond.sOPriceEnd) + 0.00001));
					}

					return bRet;
				}
			}
			return false;
		}
		else
		{
			return false;
		}
	}
	else
	{
		return instance().GetCompanyOfrInfoById(Cond, nID);
	}
	return false;
}

bool CBondContainer::GetBondClntdbPrice(const BLHCONDITION & Cond, int nID )
{
	if( nID<0 || nID>=instance().GetSize())
		return false;

	BKQUOTE quote={0};
	if(instance().GetClentInfoById(Cond.sCompanyid,nID,quote))
	{
		BKQUOTE* pRep=&quote;
		if( strcmp(pRep->m_BidStatus,"1")!=0 || strcmp(pRep->m_OfrStatus,"1")!=0)return false;//双边无报价
		return ( (!IsEmpty(pRep->m_Bid) && strcmp(pRep->m_BidStatus,"1")==0) && 
			(!IsEmpty(pRep->m_Ofr) && strcmp(pRep->m_OfrStatus,"1")==0));//有效报价
	}
	return false;
}

unsigned char CBondContainer::GetCFETSSpeedType(const std::string& sDes)
{
	if (sDes.find("T+0") != sDes.npos) {
		return 0x1;
	}
	else if (sDes.find("T+1") != sDes.npos) {
		return 0x2;
	}
	return 0;
}

bool CBondContainer::GetCltOffsetEstPrc(const BLHCONDITION & Cond, int nID )
{
	if( nID<0 || nID>=instance().GetSize())
		return false;

	BKQUOTE quote={0};
	if(instance().GetClentInfoById(Cond.sCompanyid,nID,quote))
	{
		BKQUOTE* pRep=&quote;
		QDateTime sCurTm = QDateTime::currentDateTime();
		QDateTime sTime = QDateTime::fromSecsSinceEpoch(pRep->m_Time);
		if( pRep->m_Time>0 && sTime.date().day()!=sCurTm.date().day())
			return true;
	}
	
	return false;
}

bool CBondContainer::GetMaturityRange(const BLHCONDITION & Cond,const CBondInfo & Info, bool bSecondaryMarket)
{
	int nSize = sizeof(Cond.nRange)/sizeof(uint32_t);
	for( int i=0; i<nSize; i++)
	{
		switch( Cond.nRange[i] ){
			case RangeOther:
				if(IsEmpty(Cond.sDate1) && IsEmpty(Cond.sDate2))return true;
				break;
			case RangeDate:
				if(IsEmpty(Cond.sDate1) && IsEmpty(Cond.sDate2))return true;
				break;
			default:
				break;
		}
	}
	if (IsEmpty(Info.GetMaturityDate()))return false;
	
	LONG ldays = 0;
	time_t server_time = ServerTimeMgr::instance().serverTime();
	if(bSecondaryMarket){
		time_t t = server_time;
		ldays = Info.GetRemainedDays(t);
	}
	else{
		std::string str = Info.GetMaturityTerm();
		if(str.length() > 0){
			ldays = (LONG)CalcRemainingDay(str);
		}
		else
			return false;//字典缺失期限字段，认为筛选失败
	}

	LONG lDate = atol(Info.GetMaturityDate());
	uint32_t Today = 0; //qb::base::IntDate::timeToInt(server_time);
	time_t T0 = 0; //qb::base::IntDate::IntToTime(Today);
	if ((Today % 10000) == 229) Today -= 1;

	bool bRes = false;

	for( int i=0; i<nSize; i++)
	{
		if(Cond.nRange[i]==0x00)
			return false;

		switch( Cond.nRange[i] )
		{
		case Range1:
			if( ldays <= 90 ) return true;
			else continue;
			break;
		case Range2:
			if( ldays >= 90 && ldays <= 180 ) return true;
			else continue;
			break;
		case Range3:
			if( ldays >= 180 && ldays <= 270 ) return true;
			else continue;
			break;
		case Range4:
		{
			time_t t1Y = 0;// qb::base::IntDate::IntToTime(Today + 10000);
			int d1Y = (t1Y - T0) / (60 * 60 * 24);
			if (ldays >= 270 && ldays <= d1Y)return true;
			else continue;
			break;
		}			
		case Range5:
		{
			time_t t1Y = 0;// qb::base::IntDate::IntToTime(Today + 10000);
			int d1Y = (t1Y - T0) / (60 * 60 * 24);
			time_t t3Y = 0;// qb::base::IntDate::IntToTime(Today + 30000);
			int d3Y = (t3Y - T0) / (60 * 60 * 24);
			if (ldays >= d1Y && ldays <= d3Y)return true;
			else continue;
			break;
		}
		case Range6:
		{
			time_t t3Y = 3;// qb::base::IntDate::IntToTime(Today + 30000);
			int d3Y = (t3Y - T0) / (60 * 60 * 24);
			time_t t5Y = 5;// qb::base::IntDate::IntToTime(Today + 50000);
			int d5Y = (t5Y - T0) / (60 * 60 * 24);
			if (ldays >= d3Y && ldays <= d5Y)return true;
			else continue;
			break;
		}
		case Range7:
		{
			time_t t5Y = 5;// qb::base::IntDate::IntToTime(Today + 50000);
			int d5Y = (t5Y - T0) / (60 * 60 * 24);
			time_t t7Y = 7;// qb::base::IntDate::IntToTime(Today + 70000);
			int d7Y = (t7Y - T0) / (60 * 60 * 24);
			if (ldays >= d5Y && ldays <= d7Y)return true;
			else continue;
			break;
		}
		case Range8:
		{
			time_t t7Y = 7;// qb::base::IntDate::IntToTime(Today + 70000);
			int d7Y = (t7Y - T0) / (60 * 60 * 24);
			time_t t10Y = 10;// qb::base::IntDate::IntToTime(Today + 100000);
			int d10Y = (t10Y - T0) / (60 * 60 * 24);
			if (ldays >= d7Y && ldays <= d10Y)return true;
			else continue;
			break;
		}
		case Range9:
		{
			time_t t10Y = 10;// qb::base::IntDate::IntToTime(Today + 100000);
			int d10Y = (t10Y - T0) / (60 * 60 * 24);
			if (ldays >= d10Y)return true;
			else continue;
			break;
		}
		case RangeOther:
			{
				// scofined.qi:改进性能和bug
				// 修复只有"D","Y" 会数据检查通过的问题,
				// JIRA 10495:3.3回归 经济商现券 筛选:期限 D/Y模式在上限或者下限输入框任意输入D或者Y,都有剩余期限是0的结果返回
				bool useLeft = !IsEmpty(Cond.sDate1);
				bool useRight = !IsEmpty(Cond.sDate2);
				if (!useLeft && !useRight)
					return true;
				if (Info.IsRight())
					ldays = Info.GetRemainedDays(server_time);

				float daysLeft = useLeft ? (atof(Cond.sDate1)) : 0.0f;
				float daysRight = useRight ? (atof(Cond.sDate2)) : 0.0f;
				if (useLeft && !(strrchr(Cond.sDate1, 'D') || strrchr(Cond.sDate1, 'd'))) 
					daysLeft *= 365;
				if (daysRight && !(strrchr(Cond.sDate2, 'D') || strrchr(Cond.sDate2, 'd')))
					daysRight *= 365;
				if (useLeft && !useRight)
				{
					if (ldays >= daysLeft)
						return true;
				}
				if (ldays >= daysLeft && ldays <= daysRight)
					return true;
				else
					continue;
			}
			break;
		case RangeDate:
			{
				// 旧代码中,将ldays与Cond.sDate1,Cond.sDate2做比较是不对的,格式不一样
				bool passed = true;
				if (passed && !IsEmpty(Cond.sDate1) && lDate < atol(Cond.sDate1))
					passed = false;
				if (passed && !IsEmpty(Cond.sDate2) && lDate > atol(Cond.sDate2))
					passed = false;
				if (passed)
					return true;
				else
					continue;
			}
			break;
		case RangeRealDate:
			{
				int nIndex = -1;
				int ldays1,ldays2 = 0;
				QString strDate1 = Cond.sDate1;
				QString strDate2 = Cond.sDate2;
				if(strDate1.length() <= 0 && strDate2.length() <= 0)return true;
				strDate1 = strDate1.toUpper();
				strDate2 = strDate2.toUpper();
				if(strDate1.indexOf("D")!=-1)
				{
					strDate1.replace("D","");
					ldays1 = strDate1.toInt();
				}
				else
				{
					strDate1.replace("Y","");
					ldays1=strDate1.toFloat()*365;
				}
				if(strDate2.indexOf("D")!=-1)
				{
					strDate2.replace("D","");
					ldays2=strDate2.toInt();
				}
				else
				{
					strDate2.replace("Y","");
					ldays2= strDate2.toFloat()*365;
				}
				if(Info.IsRight())
				{
					ldays = Info.GetRemainedDays(server_time);
				}
				if(strDate1.length()>0 && strDate2.length()<=0)
					if(ldays >= ldays1) return true;
				if(ldays >= ldays1 && ldays <= ldays2) return true;
				else continue;
			}
			break;
		case RangeMulDate:
			{
				time_t t = server_time;
				std::string str = Info.GetRemainPeriod(t);
				bool bRemain =false;
				if(str.size()>0)
				{
					ldays = (long)CalcRemainingDay(str);
					if(ldays>0)
					{
						bRemain = true;
					}
				}
				if(!bRemain)
				{
					if(!IsEmpty(Info.GetMaturityTerm()))
					{
						std::string str = Info.GetMaturityTerm();
						ldays = CBondContainer::CalcRemainingDay(str);
					}
					else
						ldays = 0;
				}

				int nIndex = -1;
				int ldays1,ldays2 = 0;
				QString strDate1 = Cond.sDate1;//TODO: in UTF-8
				QString strDate2 = Cond.sDate2;
				if(strDate1.length() <= 0 && strDate2.length() <= 0)return true;
				strDate1 = strDate1.toUpper();
				strDate2 = strDate2.toUpper();
				if(strDate1.indexOf("D")!=-1)
				{
					strDate1.replace("D","");
					ldays1 = strDate1.toInt();
				}
				else
				{
					strDate1.replace("Y","");
					ldays1=strDate1.toFloat()*365;
				}
				if(strDate2.indexOf("D")!=-1)
				{
					strDate2.replace("D","");
					ldays2 = strDate2.toInt();
				}
				else
				{
					strDate2.replace("Y","");
					ldays2= strDate2.toFloat()*365;
				}
				if(Info.IsRight())
				{
					ldays = Info.GetRemainedDays(server_time);
				}
				if(strDate1.length()>0 && strDate2.length()<=0)
					if(ldays >= ldays1) return true;
				if(ldays >= ldays1 && ldays <= ldays2) return true;
				else continue;
			}
			break;
		default:
			break;
		}

		if(!bRes) break;
	}
	return bRes;
}

bool CBondContainer::GetMaturityTermRange(const BLHCONDITION & Cond,const CBondInfo & Info, bool bSecondaryMarket )
{
	int nSize = sizeof(Cond.nRange) / sizeof(uint32_t);
	for (int i = 0; i < nSize; i++)
	{
		switch (Cond.nRange[i]) {
		case RangeOther:
			if (IsEmpty(Cond.sDate1) && IsEmpty(Cond.sDate2))return true;
			break;
		case RangeDate:
			if (IsEmpty(Cond.sDate1) && IsEmpty(Cond.sDate2))return true;
			break;
		case RangeRealDate:
			if (IsEmpty(Cond.sDate1) && IsEmpty(Cond.sDate2))return true;
			break;
		case RangeMulDate:
			if (IsEmpty(Cond.sDate1) && IsEmpty(Cond.sDate2))return true;
			break;
		default:
			break;
		}
	}

	int ldays = 0;
	time_t server_time = ServerTimeMgr::instance().serverTime();
	if (bSecondaryMarket) {
		time_t t = server_time;
		std::string str = Info.GetRemainPeriod(t);
		ldays = (int)CalcRemainingDay(str);
	}
	else {
		std::string str = Info.GetMaturityTerm();
		if (str.length() > 0) {
			ldays = (int)CalcRemainingDay(str);
		}
		else
			return false;//字典缺失期限字段，认为筛选失败
	}

	int lDate = atol(Info.GetMaturityDate());
	bool bRes = false;

	for (int i = 0; i < nSize; i++)
	{
		if (Cond.nRange[i] == 0x00)
			return false;

		switch (Cond.nRange[i])
		{
		case Range1:
			if (ldays <= 90) return true;
			else continue;
			break;
		case Range2:
			if (ldays >= 90 && ldays <= 180) return true;
			else continue;
			break;
		case Range3:
			if (ldays >= 180 && ldays <= 270) return true;
			else continue;
			break;
		case Range4:
			if (ldays >= 270 && ldays <= 365) return true;
			else continue;
			break;
		case Range5:
			if (ldays >= 365 && ldays <= 365 * 3) return true;
			else continue;
			break;
		case Range6:
			if (ldays >= 365 * 3 && ldays <= 365 * 5) return true;
			else continue;
			break;
		case Range7:
			if (ldays >= 365 * 5 && ldays <= 365 * 7) return true;
			else continue;
			break;
		case Range8:
			if (ldays >= 365 * 7 && ldays <= 365 * 10) return true;
			else continue;
			break;
		case Range9:
			if (ldays >= 365 * 10) return true;
			else continue;
			break;
		case RangeOther:
		{
			int nIndex = -1;
			int ldays1, ldays2 = 0;
			QString strDate1 = Cond.sDate1;
			QString strDate2 = Cond.sDate2;
			if (strDate1.length() <= 0 && strDate2.length() <= 0)return true;
			strDate1 = strDate1.toUpper();
			strDate2 = strDate2.toUpper();
			if (strDate1.indexOf("D") != -1)
			{
				strDate1.replace("D", "");
				ldays1 = strDate1.toInt();
			}
			else
			{
				strDate1.replace("Y", "");
				ldays1 = strDate1.toFloat() * 365;
			}
			if (strDate2.indexOf("D") != -1)
			{
				strDate2.replace("D", "");
				ldays2 = strDate2.toInt();
			}
			else
			{
				strDate2.replace("Y", "");
				ldays2 = strDate2.toFloat() * 365;
			}
			if (Info.IsRight())
			{
				ldays = Info.GetRemainedDays(server_time);
			}

			if (strDate1.length() > 0 && strDate2.length() <= 0)
				if (ldays >= ldays1) return true;
			if (ldays >= ldays1 && ldays <= ldays2) return true;
			else continue;
		}
		break;
		case RangeDate:
		{
			if (IsEmpty(Cond.sDate1) && IsEmpty(Cond.sDate2))return true;
			int ldays1 = atol(Cond.sDate1);
			int ldays2 = atol(Cond.sDate2);
			if (!IsEmpty(Cond.sDate1) && IsEmpty(Cond.sDate2))
				if (ldays >= ldays1) return true;
			if (lDate >= ldays1 && lDate <= ldays2) return true;
			else continue;
		}
		break;
		case RangeRealDate:
		{
			int nIndex = -1;
			int ldays1, ldays2 = 0;
			QString strDate1 = Cond.sDate1;
			QString strDate2 = Cond.sDate2;
			if (strDate1.length() <= 0 && strDate2.length() <= 0)return true;
			strDate1 = strDate1.toUpper();
			strDate2 = strDate2.toUpper();
			if (strDate1.indexOf("D") != -1)
			{
				strDate1.replace("D", "");
				ldays1 = strDate1.toInt();
			}
			else
			{
				strDate1.replace("Y", "");
				ldays1 = strDate1.toFloat() * 365;
			}
			if (strDate2.indexOf("D") != -1)
			{
				strDate2.replace("D", "");
				ldays2 = strDate2.toInt();
			}
			else
			{
				strDate2.replace("Y", "");
				ldays2 = strDate2.toFloat() * 365;
			}
			if (Info.IsRight())
			{
				ldays = Info.GetRemainedDays(server_time);
			}
			if (strDate1.length() > 0 && strDate2.length() <= 0)
				if (ldays >= ldays1) return true;
			if (ldays >= ldays1 && ldays <= ldays2) return true;
			else continue;
		}
		break;
		case RangeMulDate:
		{
			time_t t = server_time;
			std::string str = Info.GetRemainPeriod(t);
			bool bRemain = false;
			if (str.size() > 0)
			{
				ldays = (int)CalcRemainingDay(str);
				if (ldays > 0)
				{
					bRemain = true;
				}
			}
			if (!bRemain)
			{
				if (!IsEmpty(Info.GetMaturityTerm()))
				{
					std::string str = Info.GetMaturityTerm();
					ldays = CBondContainer::CalcRemainingDay(str);
				}
				else
					ldays = 0;
			}
			int nIndex = -1;
			int ldays1, ldays2 = 0;
			QString strDate1 = Cond.sDate1;
			QString strDate2 = Cond.sDate2;
			if (strDate1.length() <= 0 && strDate2.length() <= 0)return true;
			strDate1 = strDate1.toUpper();
			strDate2 = strDate2.toUpper();
			if (strDate1.indexOf("D") != -1)
			{
				strDate1.replace("D", "");
				ldays1 = strDate1.toInt();
			}
			else
			{
				strDate1.replace("Y", "");
				ldays1 = strDate1.toFloat() * 365;
			}
			if (strDate2.indexOf("D") != -1)
			{
				strDate2.replace("D", "");
				ldays2 = strDate2.toInt();
			}
			else
			{
				strDate2.replace("Y", "");
				ldays2 = strDate2.toFloat() * 365;
			}
			if (Info.IsRight())
			{
				ldays = Info.GetRemainedDays(server_time);
			}
			if (strDate1.length() > 0 && strDate2.length() <= 0)
				if (ldays >= ldays1) return true;
			if (ldays >= ldays1 && ldays <= ldays2) return true;
			else continue;
		}
		break;
		}

		if (!bRes) break;
	}
	return bRes;
}

bool    CBondContainer::GetDeadLineRange(const BLHCONDITION & Cond,const CBondInfo & Info)
{
	bool bRes = false;
	int nSize = sizeof(Cond.nRange)/sizeof(uint32_t);
	for( int i=0; i<nSize; i++)
	{
		switch( Cond.nRange[i] )
		{
			case DL_RangeDate:
				if(IsEmpty(Cond.sMTDate1) && IsEmpty(Cond.sMTDate2))return true;
				break;
			default:
				break;
		}
	}
	if(IsEmpty(Info.GetMaturityTerm()))
	{
		//LOGWARN("MaturityTerm is empty");
		return false;
	}

	double lfStartDLYear = 0.0;
	double lfEndDLYear = 0.0;
	std::string strDeadLine(Info.GetMaturityTerm());
	if(strDeadLine.length()<=0) return false;

	int nYFindIndex = strDeadLine.find('Y',0);
	int nMFindIndex = strDeadLine.find('M',0);
	int nDFindIndex = strDeadLine.find('D',0);

	double fYear = 0.0;
	if(nYFindIndex>=0)
	{
		strDeadLine.erase(nYFindIndex,1);
		fYear = atof(strDeadLine.c_str());
	}
	else if(nMFindIndex>=0)
	{
		strDeadLine.erase(nMFindIndex,1);
		fYear = atof(strDeadLine.c_str())/12.0;
	}
	else if(nDFindIndex>=0)
	{
		strDeadLine.erase(nDFindIndex,1);
		fYear = atof(strDeadLine.c_str())/365.0;
	}

	//判断条件：前开后闭
	for( int i=0; i<nSize; i++)
	{
		if(Cond.nDeadLineRange[i]==0x00)
			return false;

		switch( Cond.nDeadLineRange[i] )
		{
		case DL_Range1:
			{
				lfStartDLYear = (1-1)/12.0;
				lfEndDLYear = (1+1)/12.0;
			}
			break;
		case DL_Range2:
			{
				lfStartDLYear = (3-1)/12.0;
				lfEndDLYear = (3+1)/12.0;
			}
			break;
		case DL_Range3:
			{
				lfStartDLYear = (6-1)/12.0;
				lfEndDLYear = (6+1)/12.0;
			}
			break;
		case DL_Range4:
			{
				lfStartDLYear = (9-2)/12.0;
				lfEndDLYear = (9+2)/12.0;
			}
			break;
		case DL_Range5:
			{
				lfStartDLYear = 1-2.0/12.0;
				lfEndDLYear = 1+2.0/12.0;
			}
			break;
		case DL_Range6:
			{
				lfStartDLYear = 3-2.0/12.0;
				lfEndDLYear = 3+2.0/12.0;
			}
			break;
		case DL_Range7:
			{
				lfStartDLYear = 5-3.0/12.0;
				lfEndDLYear = 5+3.0/12.0;
			}
			break;
		case DL_Range8:
			{
				lfStartDLYear = 7-4.0/12.0;
				lfEndDLYear = 7+4.0/12.0;
			}
			break;
		case DL_Range9:
			{
				lfStartDLYear = 10-4.0/12.0;
				lfEndDLYear = 10+4.0/12.0;
			}
			break;
		case DL_Range10:
			{
				lfStartDLYear = 9.5;
				lfEndDLYear = 10000.0;
			}
			break;
		case DL_RangeDate:
			{
				lfStartDLYear = atof(Cond.sMTDate1);
				lfEndDLYear = atof(Cond.sMTDate2);
				if(!IsEmpty(Info.GetMaturityTerm()))
				{
					std::string str = Info.GetMaturityTerm();
					fYear = CBondContainer::CalcRemainingDay(str)/365.0;
				}
				else
					fYear = 0.0f;
			}
			break;
		case DL_Range21:
			{
				lfStartDLYear = 1.00001;
				lfEndDLYear = 10000.0;
			}
			break;
		default:
			break;
		}

		if( fYear <= lfEndDLYear && fYear>lfStartDLYear) return true;
		else continue;
	}

	return bRes;
}

const CSPString& CBondContainer::GetProdType( uint32_t nType )
{
	return TypeNameManager::Get().GetTypeName(kTypeCategoryProd,nType);

}

const CSPString& CBondContainer::GetRatingLevel( uint32_t nIssuerRating )
{
	return TypeNameManager::Get().GetTypeName(kTypeCategoryRating,nIssuerRating);
	
}

const CSPString& CBondContainer::GetCouponType(uint32_t nType)
{
	return TypeNameManager::Get().GetTypeName(kTypeCategoryCoupon, nType);

}

const CSPString& CBondContainer::GetInstType( uint32_t nInst )
{
	return TypeNameManager::Get().GetTypeName(kTypeCategoryInst,nInst);

}

bool	CBondContainer::GetRightType( uint32_t nType )
{
	if( nType == RightNo )
		return false;
	return true;
}

bool CBondContainer::IsETSBondType(const BLHCONDITION & Cond, const  CBondInfo & Info)
{
	int nSize = sizeof(Cond.nETSBond) / sizeof(uint32_t);
	for (int i = 0; i < nSize; i++)
	{
		if (Cond.nETSBond[i] == 0x00)
			return false;

		switch (Cond.nETSBond[i])
		{
		case CBondContainer::ETSBondAll:
			return true;
			break;
		case CBondContainer::ETSBondYes:
			if (Info.IsETSBond())
			{
				return true;
			}
			break;
		case CBondContainer::ETSBondNo:
			if (!Info.IsETSBond())
			{
				return true;
			}
			break;
		default:
			break;
		}
	}

	return false;
}

bool CBondContainer::IsCorpBondType(const BLHCONDITION & Cond, const CBondInfo & Info)
{
	int nSize = sizeof(Cond.nCorpBond) / sizeof(uint32_t);
	for (int i = 0; i < nSize; i++)
	{
		if (Cond.nCorpBond[i] == 0x00)
			return false;

		switch (Cond.nCorpBond[i])
		{
		case CBondContainer::CorpBondAll:
			return true;
			break;
		case CBondContainer::CorpBond_Public:
			if (Info.IsPubliceCorpBond())
			{
				return true;
			}
			break;
		case CBondContainer::CorpBond_Private:
			if (Info.IsPrivateCorpBond())
			{
				return true;
			}
			break;
		default:
			break;
		}
	}

	return false;
}

bool  CBondContainer::IsPlatformType(const BLHCONDITION & Cond, const CBondInfo & Info)
{
	if (!Info.IsMunicipal()) return false;
	int nSize = sizeof(Cond.nPlatform) / sizeof(uint32_t);
	
	CQBIssuerInfo &IMap = CQBIssuerInfo::instance();
	const IssuerInfo* pI = IMap.GetIssuerInfo(Info.GetIssuerCode());
	static char stPlatLevel[16 + 1] = { 0 };
	stPlatLevel[0] = '\0';
	if (pI != nullptr && !IsEmpty(pI->field((int)kIssuerInfo::Municipal_code))){
		const QBPROVINCEINFO* pArea = CQBProvinceInfo::instance().GetProviceInfo(pI->field((int)kIssuerInfo::Municipal_code));
		if (pArea != nullptr)	FIELDCOPY(stPlatLevel, pArea->Area_Level);
	}
	for (int i = 0; i < nSize; i++){
		switch (Cond.nPlatform[i]){
		case CBondContainer::PlatforamAll:
			return true;
			break;
		case CBondContainer::Platforam_Province:
			if (strcmp(stPlatLevel,"PRN") == 0){
				return true;
			}
			break;
		case CBondContainer::Platforam_City:
			if (strcmp(stPlatLevel, "CTY") == 0){
				return true;
			}
			break;
		case CBondContainer::Platforam_Area:
			if (strcmp(stPlatLevel, "TWN") == 0){
				return true;
			}
			break;
		case CBondContainer::Platforam_Other:
			if (strcmp(stPlatLevel, "VIL") == 0 || strcmp(stPlatLevel, "ARE") == 0 ||
				strcmp(stPlatLevel, "IND") == 0 || strcmp(stPlatLevel, "OTH") == 0){
				return true;
			}
			break;
		default:
			break;
		}
	}
	
	return false;
}

bool  CBondContainer::IsLocalBond(const BLHCONDITION & Cond, const CBondInfo & Info)
{
	int nSize = sizeof(Cond.nLocalBond) / sizeof(uint32_t);
	for (int i = 0; i < nSize; i++){
		switch (Cond.nLocalBond[i]){
		case CBondContainer::LocalBondAll:
			return true;
			break;
		case CBondContainer::LocalBond_Normal:
			if (strcmp(Info.GetBondSubType(), "LLB") == 0 && strcmp(Info.GetEntCor(), "SMB") == 0){
				return true;
			}
			break;
		case CBondContainer::LocalBond_Special:
			if (strcmp(Info.GetBondSubType(), "LLB") == 0 && strcmp(Info.GetEntCor(), "NMB") == 0){
				return true;
			}
			break;
		default:
			break;
		}
	}

	return false;
}

bool	CBondContainer::GetWarrType(const BLHCONDITION & Cond, const  CBondInfo & Info)
{
	int nSize = sizeof(Cond.nWarrant)/sizeof(uint32_t);
	for( int i=0; i<nSize; i++)
	{
		if(Cond.nWarrant[i]==0x00)
			return false;

		switch( Cond.nWarrant[i] )
		{
		case CBondContainer::WarrPeople:
			{
				const char * pWarrant = Info.GetWarrant();
				if ( pWarrant!=nullptr && strstr(pWarrant,"GUA") != nullptr)
				{
					return true;
				}
			}
			break;
		case CBondContainer::WarrObject:
			{
				const char * pWarrant = Info.GetWarrant();
				if ( pWarrant!=nullptr && strstr(pWarrant,"SEC") != nullptr)
				{
					return true;
				}
			}
			break;
		case CBondContainer::WarrCRM:
			{
				const BOND_CRM_CLAUSE* pCrm = QBCRMBond::instance().GetBondByReferKey(Info.GetCombBondKey());
				if (pCrm)
				{
					std::string bklm;
					CBondInfo *pInfo;
					while (1)
					{
						std::string sBK(pCrm->BondKey);
						bklm = sBK + ".CIB";
						pInfo = instance().GetBond(bklm);
						if (pInfo)
						{
							if (strcmp(pInfo->GetBondSubType(), "CRM") == 0)return true;
							break;
						}
						bklm = sBK + ".SSE";
						pInfo = instance().GetBond(bklm);
						if (pInfo)
						{
							if (strcmp(pInfo->GetBondSubType(), "CRM") == 0)return true;
							break;
						}
						bklm = sBK + ".SZE";
						pInfo = instance().GetBond(bklm);
						if (pInfo)
						{
							if (strcmp(pInfo->GetBondSubType(), "CRM") == 0)return true;
							break;
						}
						break;
					}
				}
			}
	
			break;
		case CBondContainer::WarrCLN:
			{
				const BOND_CRM_CLAUSE* pCrm = QBCRMBond::instance().GetBondByReferKey(Info.GetCombBondKey());
				if (pCrm)
				{
					std::string bklm;
					CBondInfo *pInfo;
					while (1)
					{
						std::string sBK(pCrm->BondKey);
						bklm = sBK + ".CIB";
						pInfo = instance().GetBond(bklm);
						if (pInfo)
						{
							if (strcmp(pInfo->GetBondSubType(), "CLN") == 0)return true;
							break;
						}
						bklm = sBK + ".SSE";
						pInfo = instance().GetBond(bklm);
						if (pInfo)
						{
							if (strcmp(pInfo->GetBondSubType(), "CLN") == 0)return true;
							break;
						}
						bklm = sBK + ".SZE";
						pInfo = instance().GetBond(bklm);
						if (pInfo)
						{
							if (strcmp(pInfo->GetBondSubType(), "CLN") == 0)return true;
							break;
						}
						break;
					}
				}
			}

			break;
		case CBondContainer::WarrOther:
			return !Info.IsWarranted();
		    break;
		default:
		    break;
		}
	}

	return false;
}


bool CBondContainer::GetMunicpType(const  BLHCONDITION & Cond, const  CBondInfo & Info)
{
	/*
	1、既是平台又是城投，选中平台；
	2、是城投，但非平台，选中城投；
	3、其余为非城投；
	*/

	int nSize = sizeof(Cond.nMunicp)/sizeof(uint32_t);
	for( int i=0; i<nSize; i++)
	{
		if(Cond.nMunicp[i]==CBondContainer::MunicNone)
			return false;

		switch( Cond.nMunicp[i] )
		{
		case CBondContainer::MunicYes:
			{
				if ( Info.IsMunicipal())
				{
					return true;
				}
			}
			break;
		case CBondContainer::MunicNo:
			{
				if ( !Info.IsMunicipal())
				{
					return true;
				}
			}
			break;
		case CBondContainer::MnuicPlatform:
			{
				if ( Info.IsMunicipal() && Info.IsCBRC_Financing_Platform() )
				{
					return true;
				}
			}
			break;
		default:
			break;
		}
	}

	return false;
}


bool CBondContainer::RetrieveFromStatic( int bondType, const char * szType, std::vector<int>& array_result )
{
	FilterTypes nType = (FilterTypes)bondType;
	if( nType == typeNone )
	{
		return true;
	}

	if( nType < typeMin || nType > typeMax )
		return false;

	bool bCheck2 = true;
	if( nType == typeBondType || nType == typeOption )
	{
		if( nullptr == szType || IsEmpty(szType))
			nType = typeAll;
	}
	if (szType == nullptr)
		return false;

	HUGELOCK(m_mutex);
	int nSize = GetSize();
	switch( nType )
	{
	case typeBondType:
		{
			int	nCount	=	0;
			for( int i=0; i<nSize; i++ )//BIGLOOP
			{
				const CBondInfo	& info = ElementAtR(i);
				if ( info.IsAddIssueBond() )
					continue;
				if (szType && strcmp(szType, info.GetBondSubType()) == 0)
				{
					array_result.push_back(i);
					nCount	++;
				}
			}
		}
		break;
	case typeExternal:
	case typeAttribute:
	case typeCoupon:
	case typeOption:
	case typeArgument:
	case typeDate:
	case typeRating:
		break;
	case typeBondID:
		{
			int	nCount	=	0;
			int nTypeLen = szType?strlen(szType):0;
			for (int i = 0; i<nSize; i++)//BIGLOOP
			{
				const CBondInfo	& info = ElementAtR(i);
				if ( info.IsAddIssueBond() )
					continue;
				if( GetMaturityBond(info) ) 
					continue;

				if (strncmp(info.GetCombBondCode(), szType, nTypeLen) == 0 ||
					strstr(info.GetBondShortName(),szType) ||
					strstr(const_cast<char*>(info.GetBondJianpin().c_str()), szType)
					)
				{
					//GetBondPinyin
					array_result.push_back(i);
					nCount	++;
				}
			}
		}
		break;
	case typeBondKey:
		{
			int	nCount	=	0;
			for (int i = 0; i<nSize; i++)//BIGLOOP
			{
				const CBondInfo	& info = ElementAtR(i);
				if ( info.IsAddIssueBond() )
					continue;
				if( GetMaturityBond(info) ) 
					continue;
				if (strcmp(szType, info.GetCombBondKey()) == 0)
				{
					array_result.push_back(i);
					nCount	++;
				}
			}
		}
		break;
	case typeBondExpiry:
		{
			int	nCount	=	0;
			time_t tnow = (time_t)szType;
			const char* expired = strBondLib_Expired()/*"已到期"*/;
			for (int i = 0; i<nSize; i++)//BIGLOOP
			{
				const CBondInfo	& info = ElementAtR(i);
				if ( info.IsAddIssueBond() )
					continue;
				if (strcmp(info.GetRemainDate(), expired) != 0){
					array_result.push_back(i);
					nCount	++;
				}
			}
		}
		break;
	case typeMarketType:
		{
			for (int i = 0; i<nSize; i++)//BIGLOOP
			{
				const CBondInfo	& info = ElementAtR(i);
				if ( info.IsAddIssueBond() )
					continue;
				if(qstricmp(info.GetMarketType(),szType)==0){
					array_result.push_back(i);}
			}
		}
		break;
	case typeBondSubType:
		{
			for (int i = 0; i<nSize; i++)//BIGLOOP
			{
				const CBondInfo	& info = ElementAtR(i);
				if ( info.IsAddIssueBond() ) continue;
				if( info.CheckBontSubType(szType) )	
					array_result.push_back(i);
			}
		}
		break;
	case typeBondIDInSSE://上证固收
	{
		int	nCount = 0;
		int nTypeLen = szType ? strlen(szType) : 0;
		for (int i = 0; i < nSize; i++)//BIGLOOP
		{
			const CBondInfo	& info = ElementAtR(i);
			if (info.IsAddIssueBond())continue;
			if (strcmp(info.GetListedMarket(), "SSE") != 0)continue;//剔除非上交所
			if (info.CheckAssetStatus(CBondContainer::AssetPri))continue;//剔除私募
			if (GetMaturityBond(info))continue;

			if (strncmp(info.GetCombBondCode(), szType, nTypeLen) == 0 ||
				strstr(info.GetBondShortName(), szType) ||
				strstr(const_cast<char*>(info.GetBondJianpin().c_str()), szType)
				)
			{
				//GetBondPinyin
				array_result.push_back(i);
				nCount++;
			}
		}
	}
	break;
	case typeBondKeyInSSE://上证固收
	{
		int	nCount = 0;
		for (int i = 0; i < nSize; i++)//BIGLOOP
		{
			const CBondInfo	& info = ElementAtR(i);
			if (info.IsAddIssueBond())continue;
			if (strcmp(info.GetListedMarket(), "SSE") != 0)continue;//剔除非上交所
			if (info.CheckAssetStatus(CBondContainer::AssetPri))continue;//剔除私募
			if (GetMaturityBond(info))continue;
			if (strcmp(szType, info.GetCombBondKey()) == 0)
			{
				array_result.push_back(i);
				nCount++;
			}
		}
	}
	break;
	default:
		////SP_ASSERT( false );
		return false;
	}

	return true;
}

bool CBondContainer::RetrieveFromStaticCFETS(int bondType, const char * szType, std::vector<int>& array_result)
{
	FilterTypes nType = (FilterTypes)bondType;
	if (nType == typeNone)
	{
		return true;
	}

	if (nType < typeMin || nType > typeMax)
		return false;

	bool bCheck2 = true;
	if (nType == typeBondType || nType == typeOption)
	{
		if (nullptr == szType || IsEmpty(szType))// && (nullptr == szSubType || IsEmpty(szSubType)) )
			nType = typeAll;
	}
	if (szType == nullptr)
		return false;

	HUGELOCK(m_mutex);
	int nSize = GetSize();
	switch (nType)
	{
	case typeBondType:
	{
		int	nCount = 0;
		for (int i = 0; i < nSize; i++)//BIGLOOP
		{
			const CBondInfo	& info = ElementAtR(i);
			if (info.IsAddIssueBond() || info.IsExchange())
				continue;
			if (szType && strcmp(szType, info.GetBondSubType()) == 0)
			{
				array_result.push_back(i);
				nCount++;
			}
		}
	}
	break;
	case typeExternal:
	case typeAttribute:
	case typeCoupon:
	case typeOption:
	case typeArgument:
	case typeDate:
	case typeRating:
		break;
	case typeBondID:
	{
		int	nCount = 0;
		int nTypeLen = szType ? strlen(szType) : 0;
		for (int i = 0; i < nSize; i++)//BIGLOOP
		{
			const CBondInfo	& info = ElementAtR(i);
			if (info.IsAddIssueBond() || info.IsExchange())
				continue;
			if (GetMaturityBond(info))
				continue;

			if (strncmp(info.GetCombBondCode(), szType, nTypeLen) == 0 ||
				strstr(info.GetBondShortName(), szType) ||
				strstr(const_cast<char*>(info.GetBondJianpin().c_str()), szType)
				)
			{
				//GetBondPinyin
				array_result.push_back(i);
				nCount++;
			}
		}
	}
	break;
	case typeBondKey:
	{
		int	nCount = 0;
		for (int i = 0; i < nSize; i++)//BIGLOOP
		{
			const CBondInfo	& info = ElementAtR(i);
			if (info.IsAddIssueBond() || info.IsExchange())
				continue;
			if (GetMaturityBond(info))
				continue;
			if (strcmp(szType, info.GetCombBondKey()) == 0)
			{
				array_result.push_back(i);
				nCount++;
			}
		}
	}
	break;
	case typeBondExpiry:
	{
		int	nCount = 0;
		time_t tnow = (time_t)szType;
		const char* expired = strBondLib_Expired()/*"已到期"*/;
		for (int i = 0; i < nSize; i++)//BIGLOOP
		{
			const CBondInfo	& info = ElementAtR(i);
			if (info.IsAddIssueBond() || info.IsExchange())
				continue;
			if (strcmp(info.GetRemainDate(), expired) != 0){
				array_result.push_back(i);
				nCount++;
			}
		}
	}
	break;
	case typeMarketType:
	{
		for (int i = 0; i < nSize; i++)//BIGLOOP
		{
			const CBondInfo	& info = ElementAtR(i);
			if (info.IsAddIssueBond() || info.IsExchange())
				continue;
			if (qstricmp(info.GetMarketType(), szType) == 0){
				array_result.push_back(i);
			}
		}
	}
	break;
	case typeBondSubType:
	{
		for (int i = 0; i < nSize; i++)//BIGLOOP
		{
			const CBondInfo	& info = ElementAtR(i);
			if (info.IsAddIssueBond() || info.IsExchange())
			if (info.CheckBontSubType(szType))
				array_result.push_back(i);
		}
	}
	break;
	default:
		////SP_ASSERT(false);
		return false;
	}

	return true;
}

bool CBondContainer::RetrieveFromStaticSSEFI(int bondType, const char * szType, std::vector<int>& array_result)
{
	FilterTypes nType = (FilterTypes)bondType;
	if (nType == typeNone)
	{
		return true;
	}

	if (nType < typeMin || nType > typeMax)
		return false;

	if (szType == nullptr)
		return false;

	HUGELOCK(m_mutex);
	int nSize = GetSize();
	switch (nType)
	{
	case typeBondID:
	{
		int	nCount = 0;
		int nTypeLen = szType ? strlen(szType) : 0;
		for (int i = 0; i < nSize; i++)//BIGLOOP
		{
			const CBondInfo	& info = ElementAtR(i);
			if (strcmp(info.GetListedMarket(), "SSE") != 0) continue;
			if (info.IsAddIssueBond()) continue;
			if (GetMaturityBond(info)) continue;

			if (strncmp(info.GetCombBondCode(), szType, nTypeLen) == 0 ||
				strstr(info.GetBondShortName(), szType) ||
				strstr(const_cast<char*>(info.GetBondJianpin().c_str()), szType)
				)
			{
				//GetBondPinyin
				array_result.push_back(i);
				nCount++;
			}
		}
	}
	break;
	case typeBondKey:
	{
		int	nCount = 0;
		for (int i = 0; i < nSize; i++)//BIGLOOP
		{
			const CBondInfo	& info = ElementAtR(i);
			if (strcmp(info.GetListedMarket(), "SSE") != 0) continue;
			if (info.IsAddIssueBond()) continue;
			if (GetMaturityBond(info)) continue;
			if (strcmp(szType, info.GetCombBondKey()) == 0)
			{
				array_result.push_back(i);
				nCount++;
			}
		}
	}
	break;
	default:
		//SP_ASSERT(false);
		return false;
	}

	return true;
}

bool CBondContainer::iRetrive(const BLHCONDITION& condStr, 
							  std::vector<int>& array_result, 
							  bool bSecondaryMarket /* = true */, 
							  int nCallBackType /* = CBondInfo::FCT_NULL */, 
							  _BONDFILTER BondFilter /* = nullptr */)
{
	if( condStr.nBrokId[0]==0 && IsEmpty(condStr.sCompanyid) )
	{
		return false;
	}

	HUGELOCK(m_mutex);
	if(condStr.isAllin())
	{
		int nSize = GetSize();
		array_result.reserve(nSize);
		for( int i=0; i<nSize; i++ )//BIGLOOP
			array_result.push_back(i);
	}
	else
	{
		int	nCount	=	0;
		int nSize = GetSize();
		for (int i = 0; i<nSize; i++)//BIGLOOP
		{
			bool bContinue = true;
			const CBondInfo	& info = ElementAtR(i);
			if( bContinue && condStr.nValid != 0 && !IsBCQuoteValid(condStr,i) )
				bContinue = false;
			if( bContinue && condStr.nBothFlg != 0 && !IsBilateralPrice(condStr,i) )
				bContinue = false;
			if( bContinue && condStr.nNewFlg != 0 && !info.IsNewBond() )
				bContinue = false;
			if( bContinue && condStr.nHasFlg != 0 && !IsHasPrice(condStr,i) )
				bContinue = false;
			if( bContinue && condStr.nMatFlg != 0 && GetMaturityBond(info) )
				bContinue = false;
			if( bContinue && condStr.nASemi != 0 && GetRebateBond(info) )
				bContinue = false;
			if( bContinue && condStr.nMortgt != 0 && !info.IsMortgage() )
				bContinue = false;
			if( bContinue && condStr.nCrosmk != 0 && !info.IsCrossMarket() )
				bContinue = false;
			if( bContinue && condStr.nEntrTyp != 0 && !GetSOEenterType(condStr,info) )
				bContinue = false;
			if( bContinue && condStr.nOffset != 0 && !GetBondOffsetEstPrc(condStr,i) )
				bContinue = false;
			if( bContinue && !IsEmpty(condStr.sDiffPrice) && !GetDiffPrice(condStr,i) )
				bContinue = false;
			if (bContinue && (!IsEmpty(condStr.sBPrice) || !IsEmpty(condStr.sBPriceEnd)) && !GetBidCndPrice(condStr, i))
				bContinue = false;
			if (bContinue && (!IsEmpty(condStr.sOPrice) || !IsEmpty(condStr.sOPriceEnd)) && !GetOfrCndPrice(condStr, i))
				bContinue = false;
			if( bContinue && condStr.nCommonUse[0] != CBondContainer::CommAll && !info.CheckCommonUseType(condStr)) //常用
				bContinue = false;

			if( bContinue && condStr.nType[0] != CBondContainer::BondAll && !info.CheckBondType(condStr,nCallBackType==CBondInfo::FCT_TYPE?BondFilter:nullptr)) //产品
				bContinue = false;

			if( bContinue && condStr.nIssuerRating[0] != RatingAll && !GetMultiLevel(condStr,info))
				bContinue = false;

			if (bContinue && condStr.nOutlookRating[0] != OutlookRatingAll && !GetOutlookRatingLevel(condStr, info))
				bContinue = false;
			
			if (bContinue && condStr.nCDCRating[0] != CDCRatingAll && !GetCDCRatingLevel(condStr, info))
				bContinue = false;
			if (bContinue && condStr.nCSIRating[0] != CSIRatingAll && !GetCSIRatingLevel(condStr, info))
				bContinue = false;
			if (bContinue && condStr.nCBRRating[0] != CBRRatingAll && !GetCBRRatingLevel(condStr, info))
				bContinue = false;

			if( bContinue && condStr.nWarrant[0] != WarrAll && !GetWarrType(condStr,info))
				bContinue = false;
			if( bContinue && condStr.nCouponType[0] != CouponAll && !GetMultiCouponType(condStr,info))
				bContinue = false;
			if( bContinue && condStr.nRight != RightAll && GetRightType(condStr.nRight) != info.IsRight())
				bContinue = false;
			if( bContinue && condStr.nRange[0] != RangeAll && !GetMaturityRange(condStr,info, bSecondaryMarket ) )
				bContinue = false;
			if( bContinue && condStr.nMunicp[0] != MunicAll && !GetMunicpType(condStr,info))
				bContinue = false;
			if( bContinue && condStr.nInterbank != 0 && !info.IsInterbank())
				bContinue = false;
			if( bContinue && condStr.nExchange != 0 && !info.IsExchange())
				bContinue = false;
			if( bContinue && condStr.nInstion[0] != InstAll && !GetMultiInstion(condStr,info))
				bContinue = false;
			if( bContinue && condStr.szIssuer[0][0] != '\0' && !info.CheckIssuer(condStr))
				bContinue = false;
			if( bContinue && condStr.szSector[0][0] != '\0' && !info.CheckSector(condStr))
				bContinue = false;
			if (bContinue && condStr.szSector2021[0][0] != '\0' && !info.CheckSector2021(condStr))
				bContinue = false;
			if( bContinue && condStr.szArea[0][0] != '\0' && !info.CheckArea(condStr))
				bContinue = false;
			if( bContinue && condStr.szSubType[0][0] != '\0' && !info.CheckBontSubType(condStr))
				bContinue = false;
			if( bContinue && condStr.nDebtRating[0] != DRatingNone && !info.CheckDebtRating(condStr))
				bContinue = false;
			if( bContinue && condStr.nFinDebt[0] != FinDebtNone && !info.CheckFinDebt(condStr))
				bContinue = false;
			if (bContinue && condStr.nPlatform[0] != PlatforamAll && !IsPlatformType(condStr, info))//平台债
				bContinue = false;
			if (bContinue && condStr.nLocalBond[0] != LocalBondAll && !IsLocalBond(condStr, info))//地方债
				bContinue = false;
			// add  by lbl  NCD  
			if (bContinue && condStr.nNCDRating[0] != NCDRatingAll && !info.CheckNCDRating(condStr))//NCD
				bContinue = false;
			// end 
			if( bContinue && condStr.nIssueYear[0] != 0 && !info.CheckIssueYear(condStr))
				bContinue = false;
			if( bContinue && condStr.nStateType != 0 && !GetStateType(condStr,info))
				bContinue = false;
			if(bContinue && condStr.szIssueDateB[0] != 0 && condStr.szIssueDateE[0] != 0 && !GetIssueStartDate(condStr,info))
				bContinue = false;
			if(bContinue && condStr.szUnderwriter[0] != 0 && !info.CheckUnderwriter(condStr))
				bContinue = false;
			if( bContinue && condStr.nCreditBond != 0 && !info.IsCreditBond(condStr))
				bContinue = false;
			if (bContinue && condStr.nExpireInHoliday == 1 && info.IsExpireInHoliday())//不含假期
				bContinue = false;
			if( bContinue && !info.IsInDays(condStr))
				bContinue = false;
			if( bContinue )
			{
				array_result.push_back(i);
				nCount	++;
			}
		}
	}

	return true;
}

bool CBondContainer::RetrieveFromStatic(const BLHCONDITION & condStr, std::vector<int>& array_result, bool bSecondaryMarket )
{
	if( condStr.nBrokId[0]==0 && IsEmpty(condStr.sCompanyid) )
	{
		return false;
	}

	HUGELOCK(m_mutex);
	if(condStr.isAllin()){
		int nSize = GetSize();
		array_result.reserve(nSize);
		for( int i=0; i<nSize; i++ )//BIGLOOP
			array_result.push_back(i);
	}
	else
	{
		int	nCount	=	0;
		int nSize = GetSize();
		for( int i=0; i<nSize; i++ )//BIGLOOP
		{
			bool bContinue = true;
			const CBondInfo	& info = ElementAtR(i);
			if( bContinue && condStr.nValid != 0 && !IsBCQuoteValid(condStr,i) )
				bContinue = false;
			if( bContinue && condStr.nBothFlg != 0 && !IsBilateralPrice(condStr,i) )
				bContinue = false;
			if( bContinue && condStr.nNewFlg != 0 && !info.IsNewBond() )
				bContinue = false;
			if( bContinue && condStr.nHasFlg != 0 && !IsHasPrice(condStr,i) )
				bContinue = false;
			if( bContinue && condStr.nMatFlg != 0 && GetMaturityBond(info) )
				bContinue = false;
			if( bContinue && condStr.nASemi != 0 && GetRebateBond(info) )
				bContinue = false;
			if( bContinue && condStr.nMortgt != 0 && !info.IsMortgage() )
				bContinue = false;
			if( bContinue && condStr.nCrosmk != 0 && !info.IsCrossMarket() )
				bContinue = false;
			if( bContinue && condStr.nEntrTyp != 0 && !GetSOEenterType(condStr,info) )
				bContinue = false;
			if( bContinue && condStr.nOffset != 0 && !GetBondOffsetEstPrc(condStr,i) )
				bContinue = false;
			if( bContinue && !IsEmpty(condStr.sDiffPrice) && !GetDiffPrice(condStr,i) )
				bContinue = false;
			if (bContinue && (!IsEmpty(condStr.sBPrice) || !IsEmpty(condStr.sBPriceEnd)) && !GetBidCndPrice(condStr, i))
				bContinue = false;
			if (bContinue && (!IsEmpty(condStr.sOPrice) || !IsEmpty(condStr.sOPriceEnd)) && !GetOfrCndPrice(condStr, i))
				bContinue = false;
			if( bContinue && condStr.nCommonUse[0] != CBondContainer::CommAll && !info.CheckCommonUseType(condStr)) //常用
				bContinue = false;
			if( bContinue && condStr.nType[0] != BondAll && !info.CheckBondType(condStr))
				bContinue = false;
			if( bContinue && condStr.nIssuerRating[0] != RatingAll && !GetMultiLevel(condStr,info))
				bContinue = false;

			if (bContinue && condStr.nOutlookRating[0] != OutlookRatingAll && !GetOutlookRatingLevel(condStr, info))
				bContinue = false;

			if (bContinue && condStr.nCDCRating[0] != CDCRatingAll && !GetCDCRatingLevel(condStr, info))
				bContinue = false;
			if (bContinue && condStr.nCSIRating[0] != CSIRatingAll && !GetCSIRatingLevel(condStr, info))
				bContinue = false;
			if (bContinue && condStr.nCBRRating[0] != CBRRatingAll && !GetCBRRatingLevel(condStr, info))
				bContinue = false;

			if( bContinue && condStr.nWarrant[0] != WarrAll && !GetWarrType(condStr,info))
				bContinue = false;
			if( bContinue && condStr.nCouponType[0] != CouponAll && !GetMultiCouponType(condStr,info))
				bContinue = false;
			if( bContinue && condStr.nRight != RightAll && GetRightType(condStr.nRight) != info.IsRight())
				bContinue = false;
			if( bContinue && condStr.nRange[0] != RangeAll && !GetMaturityRange(condStr,info, bSecondaryMarket ) )
				bContinue = false;
			if( bContinue && condStr.nMunicp[0] != MunicAll && !GetMunicpType(condStr,info))
				bContinue = false;
			if( bContinue && condStr.nInterbank != 0 && !info.IsInterbank())
				bContinue = false;
			if( bContinue && condStr.nExchange != 0 && !info.IsExchange())
				bContinue = false;
			if( bContinue && condStr.nInstion[0] != InstAll && !GetMultiInstion(condStr,info))
				bContinue = false;
			if( bContinue && condStr.szIssuer[0][0] != '\0' && !info.CheckIssuer(condStr))
				bContinue = false;
			if( bContinue && condStr.szSector[0][0] != '\0' && !info.CheckSector(condStr))
				bContinue = false;
			if (bContinue && condStr.szSector2021[0][0] != '\0' && !info.CheckSector2021(condStr))
				bContinue = false;
			if( bContinue && condStr.szArea[0][0] != '\0' && !info.CheckArea(condStr))
				bContinue = false;
			if( bContinue && condStr.szSubType[0][0] != '\0' && !info.CheckBontSubType(condStr))
				bContinue = false;
			if( bContinue && condStr.nDebtRating[0] != DRatingNone && !info.CheckDebtRating(condStr))
				bContinue = false;
			if( bContinue && condStr.nFinDebt[0] != FinDebtNone && !info.CheckFinDebt(condStr))
				bContinue = false;
			if (bContinue && condStr.nPlatform[0] != PlatforamAll && !IsPlatformType(condStr, info))//平台债
				bContinue = false;
			if (bContinue && condStr.nLocalBond[0] != LocalBondAll && !IsLocalBond(condStr, info))//地方债
				bContinue = false;
			// add  by lbl  NCD  
			if (bContinue && condStr.nNCDRating[0] != NCDRatingAll && !info.CheckNCDRating(condStr))//NCD
				bContinue = false;			
			
			// end 

			if( bContinue && condStr.nIssueYear[0] != 0 && !info.CheckIssueYear(condStr))
				bContinue = false;
			if( bContinue && condStr.nStateType != 0 && !GetStateType(condStr,info))
				bContinue = false;
			if(bContinue && condStr.szIssueDateB[0] != 0 && condStr.szIssueDateE[0] != 0 && !GetIssueStartDate(condStr,info))
				bContinue = false;
			if(bContinue && condStr.szUnderwriter[0] != 0 && !info.CheckUnderwriter(condStr))
				bContinue = false;
			if( bContinue && condStr.nCreditBond != 0 && !info.IsCreditBond(condStr))
				bContinue = false;
			if( bContinue && !info.IsInDays(condStr))
				bContinue = false;
			if (bContinue && condStr.nETSBond[0] != CBondContainer::ETSBondAll && !IsETSBondType(condStr, info))	 //永续债
				bContinue = false;
			if (bContinue && condStr.nCorpBond[0] != CBondContainer::CorpBondAll && !IsCorpBondType(condStr, info))	 //公司债
				bContinue = false;
			if (bContinue && condStr.nAssetStatus[0] != CBondContainer::AssetAll && !info.CheckAssetStatus(condStr))//发行
				bContinue = false;
			if (bContinue && !IsEmpty(condStr.sBidCdc) && !GetBidCdcCompare(condStr, i)) //bid-中债
				bContinue = false;
			if (bContinue && !IsEmpty(condStr.sCdcOfr) && !GetCdcOfrCompare(condStr, i)) //中债-ofr
				bContinue = false;
			if (bContinue && condStr.nExpireInHoliday == 1 && info.IsExpireInHoliday())//不含假期
				bContinue = false;
			if( bContinue )
			{
				array_result.push_back(i);
				nCount	++;
			}
		}
	}

	return true;
}


bool CBondContainer::GetBondInfo( const char * szCode, const char* szMarket, CBondInfo * pInfo, int * pid )
{
	if( nullptr == szCode || IsEmpty(szCode) )
		return false;
	void * pArrayID	=	nullptr;
	std::string sKey(szCode);
	if(szMarket && !IsEmpty(szMarket)){
		if(strcmp(szMarket, CBondContainer::lmCIB)==0)sKey += ".IB";
		else if(strcmp(szMarket, CBondContainer::lmSSE)==0)sKey += ".SH";
		else if(strcmp(szMarket, CBondContainer::lmSZE)==0)sKey += ".SZ";
	}

	int bid = GetBondIndexByCodeImpl(sKey.c_str(), sKey.size());
	if (bid >= 0 && bid < GetSize())
	{
		const CBondInfo	& info = ElementAtR(bid);
		if (pInfo)
			*pInfo = info;
		if (pid)
			*pid = bid;
		return true;
	}
	

	return false;
}

bool CBondContainer::GetBondInfoByKey( const char * szKey, const char* szMarket, CBondInfo * pInfo, int * pid )
{
	if( nullptr == szKey || IsEmpty(szKey) )
	{
		//LOGDEBUG("invalid szKey:nullptr or blank");
		////BASSERTS(0, "invalid szKey:nullptr or blank");
		return false;
	}
	void * pArrayID	=	nullptr;
	std::string sKey;
	if(szMarket && !IsEmpty(szMarket)) sKey = std::string(szKey) + "." + std::string(szMarket);
	else sKey = std::string(szKey);

	int bid = -1;
	{
		//READLOCK(m_mutex);
		int bid = GetBondIndexImpl(sKey.c_str(), sKey.size());
		if (bid >= 0 && bid < GetSize())
		{
			const CBondInfo	& info = ElementAtR(bid);
			if (pInfo)
				*pInfo = info;
			if (pid)
				*pid = bid;
			return true;
		}
	}
	if (sKey.size() < 10)
	{
		//BASSERTS(sKey.size() > 10, "invalid item in m_keymap:%s-->%d", sKey.c_str(), bid);
	}
	////LOGEMERG("invalid item in m_keymap:%s-->%d", sKey,bid);
	return false;
}

const CAdditionBondInfo* CBondContainer::GetAdditionBondInfo(int nIndex){
	//NEEDLOCK,NEEDCHECK
	//直接返回CAdditionBondInfo指针
	if(nIndex < 0 || nIndex >= (int)m_vctaddi.size())return nullptr;
	return m_vctaddi[nIndex];
}

bool CBondContainer::GetBondInfoByCombCode( const char * szCode, CBondInfo * pInfo, int * pid){
	if( nullptr == szCode || IsEmpty(szCode) )
		return false;

	int bid = GetBondIndexByCodeImpl(szCode, -1);
	if (bid >= 0 && bid < GetSize())
	{
		READLOCK(m_mutex);
		const CBondInfo	& info = ElementAtR(bid);
		if (pInfo)
			*pInfo = info;
		if (pid)
			*pid = bid;
		return true;
	}


	return false;
}

bool CBondContainer::GetBondInfoByCombKey( const char * szKey, CBondInfo * pInfo, int * pid )
{
	if( nullptr == szKey || IsEmpty(szKey) )
	{
		//LOGDEBUG("invalid szKey:nullptr or blank");
		////BASSERTS(0, "invalid szKey:nullptr or blank");
		return false;
	}
	int bid = -1;
	{
		bid = GetBondIndexImpl(szKey, -1);//拿到bid,确保对应的CBondInfo不会移动位置
		if (bid >= 0 && bid < GetSize())
		{
			READLOCK(m_mutex);
			const CBondInfo	& info = ElementAtR(bid);
			if (pInfo)
				*pInfo = info;
			if (pid)
				*pid = bid;
			return true;
		}
	}
	
	//LOGEMERG("invalid item in m_keymap:%s-->%d", szKey,bid);
	return false;
}

bool CBondContainer::GetBondOffsetEstPrc(const BLHCONDITION & Cond, int nID )
{
	if( nID<0 || nID>=GetSize())
		return false;

	if( Cond.nBkClnt!=0 )
		return GetCltOffsetEstPrc( Cond, nID );

	SetBKQuoteDiff2CDCFlag(Cond.sCompanyid,nID,0,0);


	BKQUOTE quote={0};
	if(instance().GetBankInfoById(Cond.sCompanyid,nID,quote))
	{
		BKQUOTE* pRep=&quote;
		pRep->m_BidDiff2CDCFlag = 0;
		pRep->m_OfrDiff2CDCFlag = 0;
		bool needCheck = false;
		double fDelta = 0;
		if(Cond.bDiff2CDC[0] == 1)
		{
			if(!IsEmpty(Cond.sDiff2CDC[0]))
			{
				fDelta = atof(Cond.sDiff2CDC[0]) / 100;
				needCheck = true;
			}
		}
		else
		{
			READLOCK(m_mutex);
			const CBondInfo	& info = ElementAtR(nID);
			for(int i = 1; i < 9; i ++){
				if(Cond.bDiff2CDC[i] == 1 && info.CheckBondType(BondAll + i)){
					if (!IsEmpty(Cond.sDiff2CDC[i])){
						fDelta = atof(Cond.sDiff2CDC[i]) / 100;
						needCheck = true;
						break;
					}
				}
			}
		}
		if(!needCheck)return false;
		bool bIsCDCAuthValid = true;
		{
			CBondInfo* pBond = nullptr;
			pBond = GetBond(nID);
			if (pBond != nullptr){
				bIsCDCAuthValid = pBond->IsCDCAuthValid();
			}
		}
		
		if(strcmp(pRep->m_BidStatus, "0") != 0 ){
			if (CBondCDCPriceInfo::instance().GetEstimatePriceGap(bIsCDCAuthValid, nID, CBondCDCPriceInfo::price_type_yield, true, pRep->m_Bid)  > fDelta)pRep->m_BidDiff2CDCFlag = 1;
		}
		if(strcmp(pRep->m_OfrStatus, "0") != 0 ){
			if (CBondCDCPriceInfo::instance().GetEstimatePriceGap(bIsCDCAuthValid, nID, CBondCDCPriceInfo::price_type_yield, false, pRep->m_Ofr) > fDelta)pRep->m_OfrDiff2CDCFlag = 1;
		}
		SetBKQuoteDiff2CDCFlag(Cond.sCompanyid,nID,pRep->m_BidDiff2CDCFlag,pRep->m_OfrDiff2CDCFlag);
		if(pRep->m_BidDiff2CDCFlag || pRep->m_OfrDiff2CDCFlag)return true;
		
	}
	return false;
}


bool CBondContainer::IsBCQuoteValid(const BLHCONDITION & Cond, int nID ){
	CBondContainer &cont = instance();
	if( nID<0 || nID>=cont.GetSize())
		return false;

	if( Cond.nBkClnt!=0 )
		return IsQBQuoteValid( Cond, nID );

	BKQUOTE quote={0};
	if(instance().GetBankInfoById(Cond.sCompanyid,nID,quote))
	{
		BKQUOTE* pRep=&quote;
		if( (strcmp(pRep->m_BidStatus,"0")!=0 && !IsEmpty(pRep->m_Bid))
			|| (strcmp(pRep->m_OfrStatus,"0")!=0 && !IsEmpty(pRep->m_Ofr)))//有效报价，referred报价
			return true;
	}
	return false;
}

bool CBondContainer::IsQBQuoteValid(const BLHCONDITION & Cond, int nID ){
	BKQUOTE quote={0};
	if(instance().GetClentInfoById(Cond.sCompanyid,nID,quote))
	{
		BKQUOTE* pRep=&quote;
		if( (strcmp(pRep->m_BidStatus,"0")!=0 && !IsEmpty(pRep->m_Bid))
			|| (strcmp(pRep->m_OfrStatus,"0")!=0 && !IsEmpty(pRep->m_Ofr)))
			return true;
	}
	return false;
}

void CBondContainer::SetBKQuoteDiff2CDCFlag(const char* sCompanyID, int nIndex, char cBidFlag, char cOfrFlag){
	class BkQuoteDiffWriter : public CBondBankRep::ApplyCallback{
		char		m_bidflag;
		char		m_ofrflag;
	public:
		BkQuoteDiffWriter(char cBidFlag, char cOfrFlag) :m_bidflag(cBidFlag), m_ofrflag(cOfrFlag){}
		virtual bool DoModify(BKQUOTE& bkquote)
		{
			bkquote.m_BidDiff2CDCFlag = m_bidflag;
			bkquote.m_OfrDiff2CDCFlag = m_ofrflag;
			return false;
		}
	};

	CBondBankRep* ptmp = GetBankRep(nIndex);
	if (ptmp)
	{
		BkQuoteDiffWriter writer(cBidFlag, cOfrFlag);
		ptmp->ApplyModify(false, sCompanyID, &writer);
	}
	return;
}

bool CBondContainer::GetCompanyRepById(int nId, REPORT &stRep)
{
	if( nId<0 || nId>=GetSize())
		return false;
	bool	bRes = false;
	memset( &stRep, 0, sizeof(REPORT) );
	CBondCompanyRep* ptmp = GetCompanyRep(nId);
	if(ptmp && ptmp->GetSize()>0)
	{
		class CompanyRepCallback : public CBondCompanyRep::ApplyCallback{
			REPORT&		m_report;
			bool&		m_ret;
		public:
			CompanyRepCallback(REPORT& rpt, bool& ret) :m_report(rpt), m_ret(ret){}
			bool operator()(CBondCompanyRep* ptemp){ 
				if (ptemp)
					ptemp->ApplyAccess(true, "", this);
				return m_ret; 
			}
			virtual bool DoAccess(const REPORT& rep)
			{
				if (atoi(rep.m_bidinfo.m_rebate) == 1 || !IsEmpty(rep.m_bidinfo.m_sPrice))
				{
					if (atof(rep.m_bidinfo.m_sPrice) >= atof(m_report.m_bidinfo.m_sPrice))
					{
						m_report.m_bidinfo = rep.m_bidinfo;
						m_report.m_time = max(rep.m_time, m_report.m_time);
					}
					m_ret = true;
				}
				if (atoi(rep.m_askinfo.m_rebate) == 1 || !IsEmpty(rep.m_askinfo.m_sPrice))
				{
					if (IsEmpty(m_report.m_askinfo.m_sPrice) || atof(rep.m_askinfo.m_sPrice) <= atof(m_report.m_askinfo.m_sPrice))
					{
						m_report.m_askinfo = rep.m_askinfo;
						m_report.m_time = max(rep.m_time, m_report.m_time);
					}
					m_ret = true;
				}
				if (!IsEmpty(rep.m_indx_info.m_price))
				{
					m_report = rep;
					//stRep.m_indx_info = rep.m_indx_info;
					m_ret = true;
				}
				return true;
			}
		};
		return CompanyRepCallback(stRep, bRes)(ptmp);
	}

	return bRes;
}

static bool UpdatePriceBySettlement(PRICE& price, BYTE settlement)
{
	PRICE_SETTLEMENT_LIST pes;
	CBondContainer::DecodeSettlement(price, pes);

	bool found = false;
	std::string strVol, strDesc, strSettlement;
	strVol.reserve(sizeof(price.m_sVolume));
	strDesc.reserve(sizeof(price.m_description));
	strSettlement.reserve(sizeof(price.m_interpret));

	for (auto& ps : pes)
	{
		if (0 == (ps.m_type & settlement))
			continue;

		if (!strVol.empty())
			strVol.append("+");

		if (!strDesc.empty())
			strDesc.append("+");

		strVol.append(ps.m_vol);
		if (strlen(ps.m_desc) > 0)
			strDesc.append(ps.m_vol).append("(").append(ps.m_desc).append(")");
		else
			strDesc.append(ps.m_vol);

		if (!strSettlement.empty())
		{
			strSettlement.append(";");
		}
		strSettlement.append(ps.m_vol).append(",").append(ps.m_desc).append(",");
		strSettlement += ps.m_typeold;
		strSettlement += ",";
		strSettlement += ps.m_bargin;
		strSettlement += ",";
		strSettlement += ps.m_type;

		found = true;
	}

	if (!found)
	{
		FIELDCOPY(price.m_price_status, "0");
		return false;
	}
	else
	{
		FIELDCOPY(price.m_sVolume, strVol.c_str());
		if (strDesc.find('(') != -1)
			FIELDCOPY(price.m_description, strDesc.c_str());
		else
			memset(price.m_description, 0, sizeof(price.m_description));
		FIELDCOPY(price.m_interpret, strSettlement.c_str());
	}

	return true;
}

bool CBondContainer::GetCompanyRepByIdAndSettlement(int nId, const char* szBrokerId, BYTE btSettlement, REPORT & stRep)			//根据债券szBondKey和公司名称得到报价
{
	if (btSettlement == 0)return GetCompanyRepById(nId, szBrokerId, stRep);
	CBondCompanyRep* ptmp = GetCompanyRep(nId);
	if (ptmp && ptmp->GetCompanyRepByKey(szBrokerId, stRep))
	{
		bool ret1 = UpdatePriceBySettlement(stRep.m_bidinfo, btSettlement);
		bool ret2 = UpdatePriceBySettlement(stRep.m_askinfo, btSettlement);
		return ret1 || ret2;
	}

	return false;
}

bool CBondContainer::GetCompanyBidInfoById(const BLHCONDITION & Cond, int nID )
{//不满足过滤条件返回 false
	if( nID<0 || nID>=GetSize())
		return false;

	if (IsEmpty(Cond.sBPrice) && IsEmpty(Cond.sBPriceEnd))
		return true;

	CBondCompanyRep* ptmp = GetCompanyRep(nID);
	if (ptmp && ptmp->TestBidPrice(Cond))
		return true;

	return false;
}

bool CBondContainer::GetCompanyOfrInfoById(const BLHCONDITION & Cond, int nID )
{//不满足过滤条件返回 false
	if( nID<0 || nID>=GetSize())
		return false;

	if (IsEmpty(Cond.sOPrice) && IsEmpty(Cond.sOPriceEnd))
		return true;

	CBondCompanyRep* ptmp = GetCompanyRep(nID);
	if (ptmp && ptmp->TestOfrPrice(Cond))
		return true;
	
	return false;
}

bool CBondContainer::GetBankCltBidInfoById(const BLHCONDITION & Cond, int nID )
{
	class BkQuoteBidAccessor :public CBondBankRep::ApplyCallback
	{
		char			m_szBprice[10];
		char			m_szBpriceEnd[10];
		//float			m_bprice;
		int				m_nBondIndex;
		bool		    m_bIsCDCAuthValid;
		bool			m_result;
		//uint32_t			m_bidflag;	//BLHCONDITION.nBpcCnd
	public:
		BkQuoteBidAccessor(const char*pBprice, const char*pBpriceEnd, int nID, bool bIsCDCAuthValid) :
			m_nBondIndex(nID), m_result(true), m_bIsCDCAuthValid(bIsCDCAuthValid)
		{
			strcpy(m_szBprice,pBprice);
			strcpy(m_szBpriceEnd, pBpriceEnd);
		}

		bool GetResult()const{ return m_result; }
		virtual bool DoAccess(const BKQUOTE& quote)
		{
			double dGap = 0.00001;
			if (!(IsEmpty(quote.m_Bid) || strcmp(quote.m_BidStatus, "0") == 0))
			{
				double dGap = CBondCDCPriceInfo::instance().GetEstimatePriceGap(m_bIsCDCAuthValid, m_nBondIndex, CBondCDCPriceInfo::price_type_yield, true, quote.m_Bid);
				if (dGap > INVALID_CDC_VALUE)
				{
					dGap = fabs(dGap)*100.00;
				}
			}

			if (dGap<=0.00001)
			{
				m_result = false;
				return false;
			}

			float fBid = dGap;

			bool bRet = false;
			if (!IsEmpty(m_szBprice) && !IsEmpty(m_szBpriceEnd))
			{
				bRet = (fBid > (atof(m_szBprice) - 0.00001));
				if (bRet)
					bRet = (fBid < (atof(m_szBpriceEnd) + 0.00001));
			}
			else
			{
				if (!IsEmpty(m_szBprice))
					bRet = (fBid > (atof(m_szBprice) - 0.00001));

				if (!bRet && !IsEmpty(m_szBpriceEnd))
					bRet = (fBid < (atof(m_szBpriceEnd) + 0.00001));
			}

			m_result = bRet;

			return m_result;
		}
	};


	if( nID<0 || nID>=GetSize())
		return false;

	float fDiffprc = atof(Cond.sBPrice);
	CBondBankRep* ptmp = GetClntRep(nID);
	if(ptmp && ptmp->GetSize()>0)
	{
		int nOptType = CBondCDCPriceInfo::est_type_invalid;
		bool bIsCDCAuthValid = true;

		CBondInfo* pInfo = nullptr;
		pInfo = GetBond(nID);
		if (pInfo->IsCDCAuthValid())
		{
			bIsCDCAuthValid = pInfo->IsCDCAuthValid();
		}
		BkQuoteBidAccessor accessor(Cond.sBPrice,Cond.sBPriceEnd, nID, bIsCDCAuthValid);
		ptmp->ApplyAccess(true, "", &accessor);
		return accessor.GetResult();// 默认true;
	}

	return true;
}

bool CBondContainer::GetBankCltOfrInfoById(const BLHCONDITION & Cond, int nID )
{
	class BkQuoteOfrAccessor :public CBondBankRep::ApplyCallback
	{
		char			m_szOprice[10];		//sOPrice
		char			m_szOpriceEnd[10];
		int				m_nBondIndex;
		bool			m_bIsCDCAuthValid;
		bool			m_result;
		//uint32_t			m_ofrflag;	//BLHCONDITION.nOpcCnd
	public:
		BkQuoteOfrAccessor(const char*pOprice, const char*pOpriceEnd, int nID,  bool bIsCDCAuthValid) :
			m_nBondIndex(nID), m_result(true), m_bIsCDCAuthValid(bIsCDCAuthValid)
		{
			strcpy(m_szOprice, pOprice);
			strcpy(m_szOpriceEnd, pOpriceEnd);
		}

		bool GetResult()const{ return m_result; }

		virtual bool DoAccess(const BKQUOTE& quote)
		{
			double dGap = 0.00001;
			if (!(IsEmpty(quote.m_Ofr) || strcmp(quote.m_OfrStatus, "0") == 0))
			{
				dGap = CBondCDCPriceInfo::instance().GetEstimatePriceGap(m_bIsCDCAuthValid,
					m_nBondIndex, CBondCDCPriceInfo::price_type_yield, false, quote.m_Ofr);
				if (dGap > INVALID_CDC_VALUE)
					dGap = fabs(dGap)*100.00;
			}

			if (dGap <= 0.00001)
			{
				m_result = false;
				return false;
			}

			float fOfr = dGap;

			bool bRet = false;
			if (!IsEmpty(m_szOprice) && !IsEmpty(m_szOpriceEnd))
			{
				bRet = (fOfr > (atof(m_szOprice) - 0.00001));
				if (bRet)
					bRet = (fOfr < (atof(m_szOpriceEnd) + 0.00001));
			}
			else
			{
				if (!IsEmpty(m_szOprice))
					bRet = (fOfr > (atof(m_szOprice) - 0.00001));

				if (!bRet && !IsEmpty(m_szOpriceEnd))
					bRet = (fOfr < (atof(m_szOpriceEnd) + 0.00001));
			}

			m_result = bRet;

			return bRet;
		}
	};


	if( nID<0 || nID>=GetSize())
		return false;

	float fDiffprc = atof(Cond.sOPrice);
	CBondBankRep* ptmp = GetClntRep(nID);
	if(ptmp && ptmp->GetSize()>0)
	{
		bool bIsCDCAuthValid = true;
		CBondInfo* pInfo = nullptr;
		pInfo = GetBond(nID);
		if (pInfo->IsCDCAuthValid())
		{
			bIsCDCAuthValid = pInfo->IsCDCAuthValid();
		}
		BkQuoteOfrAccessor accessor(Cond.sOPrice, Cond.sOPriceEnd, nID,  bIsCDCAuthValid);
		ptmp->ApplyAccess(true, "", &accessor);
		return accessor.GetResult();// 默认true;
	}

	return true;
}


bool CBondContainer::GetClentInfoById(const std::string &szKey, int nID, BKQUOTE& quote)
{
	if( nID<0 || nID>=GetSize())
		return false;
	memset(&quote, 0, sizeof(quote));
	CBondBankRep* ptmp = GetClntRep(nID);
	return ptmp?ptmp->GetBankRepByKey(szKey, quote):false;
}

bool CBondContainer::GetCompanyRepByKey(const char * szBondKey, REPORT &stRep)
{
	/*
	接口改造正则表达式:
	(\w+)\s*\*\s*(\w+)\s*=\s*instance\(\).(\w+)\([\w\.]+,\w+\);(\s*\n\t*)if\(\s*\w+\s*\)\s*\n\s*{
	$1 quote={0};if(instance().$3($4,quote))$5{$1* $2=&quote;
	*/
	int nId = 0;
	if(GetBondInfoByCombKey(szBondKey,nullptr,&nId))
	{
		return GetCompanyRepById(nId, stRep);
	}
	return false;
}

bool CBondContainer::GetCompanyRepByKeyAndSettlement(const char * szComboBondKey, const char * szBrokerId, BYTE btSettlement, REPORT &stRep)
{
	int nId = 0;
	if (GetBondInfoByCombKey(szComboBondKey, nullptr, &nId))
	{
		return GetCompanyRepByIdAndSettlement(nId, szBrokerId, btSettlement, stRep);
	}
	return false;
}

bool CBondContainer::GetCompanyInfoById(int nID)
{
	if( nID<0 || nID>=GetSize())
		return false;

	CBondCompanyRep* ptmp = GetCompanyRep(nID);
	class CompanyInfoFinder : public CBondCompanyRep::ApplyCallback{
		bool		m_found;
	public:
		bool operator()(CBondCompanyRep* ptmp){
			m_found = false;
			if (ptmp)
				ptmp->ApplyAccess(true, "", this);
			return m_found;
		}
		virtual bool DoAccess(const REPORT& rpt)
		{
			if (strcmp(rpt.m_bidinfo.m_price_status, "0") == 0 && strcmp(rpt.m_askinfo.m_price_status, "0") == 0)
				return true;

			if ((atoi(rpt.m_bidinfo.m_rebate) == 1 && strcmp(rpt.m_bidinfo.m_price_status, "0") != 0) ||
				(atoi(rpt.m_askinfo.m_rebate) == 1 && strcmp(rpt.m_askinfo.m_price_status, "0") != 0))
			{
				m_found = true;
				return false;
			}

			if ((!IsEmpty(rpt.m_bidinfo.m_sPrice) && strcmp(rpt.m_bidinfo.m_price_status, "0") != 0) ||
				(!IsEmpty(rpt.m_askinfo.m_sPrice) && strcmp(rpt.m_askinfo.m_price_status, "0") != 0))
			{
				m_found = true;
				return false;
			}
			return true;//表示继续遍历
		}
	};
	return CompanyInfoFinder()(ptmp);
}



bool CBondContainer::GetCpicCompanyInfoById( int nID,bool bBuyPool /*= true*/ )
{
	if( nID<0 || nID>=GetSize())
		return false;

	CBondCompanyRep* ptmp = GetCompanyRep(nID);
	if(ptmp && ptmp->GetSize()>0)
	{
		class CpicCompanyInfoFinder : CBondCompanyRep::ApplyCallback{
			bool		m_found;
			bool		m_buy_pool;
		public:
			bool operator()(CBondCompanyRep* ptmp, bool bBuyPool){
				m_found = false;
				m_buy_pool = bBuyPool;
				if (ptmp)
					ptmp->ApplyAccess(true, "", this);
				return m_found;
			}
			virtual bool DoAccess(const REPORT& rpt)
			{
				if (m_buy_pool) //买入池
				{
					if (strcmp(rpt.m_bidinfo.m_price_status, "0") == 0 && strcmp(rpt.m_askinfo.m_price_status, "0") == 0)
						return true;

					if ((atoi(rpt.m_bidinfo.m_rebate) == 1 && strcmp(rpt.m_bidinfo.m_price_status, "0") != 0) ||
						(atoi(rpt.m_askinfo.m_rebate) == 1 && strcmp(rpt.m_askinfo.m_price_status, "0") != 0))
					{
						m_found = true; return false;
					}

					if ((!IsEmpty(rpt.m_bidinfo.m_sPrice) && strcmp(rpt.m_bidinfo.m_price_status, "0") != 0) ||
						(!IsEmpty(rpt.m_askinfo.m_sPrice) && strcmp(rpt.m_askinfo.m_price_status, "0") != 0))
					{
						m_found = true; return false;
					}
				}
				else //卖出池
				{
					if (strcmp(rpt.m_bidinfo.m_price_status, "0") == 0)
						return true;

					if ((atoi(rpt.m_bidinfo.m_rebate) == 1 && strcmp(rpt.m_bidinfo.m_price_status, "0") != 0))
					{
						m_found = true; return false;
					}

					if ((!IsEmpty(rpt.m_bidinfo.m_sPrice) && strcmp(rpt.m_bidinfo.m_price_status, "0") != 0))
					{
						m_found = true; return false;
					}
				}
				return true;
			}
		};
		return CpicCompanyInfoFinder()(ptmp,bBuyPool);
	}

	return false;
}


bool CBondContainer::GetCompanyRepById(int nId, const char * szBrokerId, REPORT &stRep)
{
	if( nId<0 || nId>=GetSize())
		return false;

	CBondCompanyRep* ptmp = GetCompanyRep(nId);
	if(ptmp && ptmp->GetCompanyRepByKey(szBrokerId,stRep))
	{
		return true;
	}

	return false;
}

bool CBondContainer::GetCompanyRepByIdEx( int nId, const char * szKey, REPORT &stRep, int nFlag) //flag = 0 取最新，1 取最新有效，2 取最新双边
{
	memset(&stRep,0,sizeof(REPORT));
	if( nId<0 || nId>=GetSize())
		return false;

	CBondCompanyRep* ptmp = GetCompanyRep(nId);
	return ptmp ? ptmp->GetReport(szKey, stRep, nFlag):false;
}

bool  CBondContainer::GetCompanyIdFromRep(int nId, const char * szKey, char* buf, int capcity)
{
	// 避免拷贝REPORT结构体的开销
	CBondCompanyRep* ptmp = GetCompanyRep(nId);
	if (ptmp)
	{
		const char* field = (const char*)ptmp->GetReportField(szKey, (int)kReportField::CompanyId);
		if (field)
		{
			FIELDCOPYN(buf, capcity, field);
			return true;
		}
	}
	return false;
}


bool CBondContainer::GetCompanyRepByKey(const char * szComboBondKey,const char * szBrokerId, REPORT &stRep)
{
	int nId = 0;
	if(GetBondInfoByCombKey(szComboBondKey,nullptr,&nId))
	{
		CBondCompanyRep* ptmp = GetCompanyRep(nId);
		if(ptmp && ptmp->GetCompanyRepByKey(szBrokerId,stRep))
		{
			return true;
		}
	}
	return false;
}

bool CBondContainer::GetXCQuoteByKey(const char* szBondKey, const char* szMarket, XCQUOTE& quote) {
	int nId = 0;
	if (GetBondInfoByKey(szBondKey, szMarket, nullptr, &nId))
	{
		CXCQuoteRep* ptmp = GetXCQuote(nId);
		if (ptmp && ptmp->GetQuoteByKey(szMarket, quote))
		{
			return true;
		}
	}
	return false;
}

bool CBondContainer::FilterQuoteByClearSpeed(CFETSQUOTE& quote, BYTE btSettlement)
{
	bool bBidValid{ true }, bOfrValid{ true };
	if ((GetCFETSSpeedType(quote.m_bidVolDescription) & btSettlement) == 0) {
		bBidValid = false;
		_InitializeString(quote.m_BidPriceYield);
		_InitializeString(quote.m_BidPriceClean);
		_InitializeString(quote.m_BidPriceFull);
		_InitializeString(quote.m_BidVol);
		_InitializeString(quote.m_bidVolDescription);
		quote.m_BidCompanyName = "";
		quote.m_bidversion = 0;
	}
	if ((GetCFETSSpeedType(quote.m_ofrVolDescription) & btSettlement) == 0) {
		bOfrValid = false;
		_InitializeString(quote.m_OfrPriceYield);
		_InitializeString(quote.m_OfrPriceClean);
		_InitializeString(quote.m_OfrPriceFull);
		_InitializeString(quote.m_OfrVol);
		_InitializeString(quote.m_ofrVolDescription);
		quote.m_OfrCompanyName = "";
		quote.m_ofrversion = 0;
	}
	if (!bBidValid && !bOfrValid) {
		quote.m_time = 0;
	}
	return bBidValid || bOfrValid;
}

void CBondContainer::CalcIssueDateRange(){		//计算最大最小发行日
	int nMin = 99999999;
	int nMax = -1;
	
	m_nMinIssueDate = 0;
	m_nMaxIssueDate = 0;
	int nSize = GetSize();
	HUGELOCK(m_mutex);
	for (int i = 0; i < nSize;i++)//BIGLOOP
	{
		const CBondInfo& info = ElementAtR(i);
		int nDate = atoi(info.GetIssueStartDate());
		if (nDate > 19000000)
		{
			nMin = std::min(nMin, nDate);
			nMax = std::max(nMax, nDate);
		}
	}
	if(nMin < 99999999)m_nMinIssueDate = nMin;
	if(nMax > 0)m_nMaxIssueDate = nMax;
	return;
}

int	CBondContainer::GetMinIssueDate(){
	return m_nMinIssueDate;
}

int	CBondContainer::GetMaxIssueDate(){
	return m_nMaxIssueDate;
}

time_t CBondContainer::GetModifyTimeFast(const std::string& szKey, int nID)
{
	if (nID < 0 || nID >= GetSize())
		return 0;
	CBondCompanyRep* ptmp = GetCompanyRep(nID);
	return ptmp ? ptmp->GetModifyTime(szKey) : 0;
}
bool CBondContainer::GetCompanyInfoById(const std::string& szKey, int nID, REPORT& report)
{
	if( nID<0 || nID>=GetSize())
        return false;
	memset(&report, 0, sizeof(report));
	CBondCompanyRep* ptmp = GetCompanyRep(nID);
	return ptmp ? ptmp->GetCompanyRepByKey(szKey, report) : false;
}

bool CBondContainer::GetClentQuotByKey(const char * szBondKey,const char * szKey, BKQUOTE &stQuot)
{
	int nId = 0;
	CBondInfo info;
	if (GetBondInfoByCombKey(szBondKey, &info, &nId))
	{
		CBondBankRep* ptmp = GetClntRep(nId);
		if (ptmp && ptmp->GetBankRepByKey(szKey, stQuot))
		{
			return true;
		}
	}
	return false;
}

time_t CBondContainer::GetCompanyTimeById(const std::string& szKey, int nID)
{
	if (nID < 0 || nID >= GetSize())
		return 0;

	time_t updtime = 0;
	REPORT stRep;
	memset(&stRep, 0, sizeof(stRep));
	CBondCompanyRep* ptmp = GetCompanyRep(nID);
	if (ptmp)
	{
		ptmp->GetCompanyRepByKey(szKey, stRep);
		updtime = stRep.m_time > 0 ? stRep.m_time : max(stRep.m_askinfo.m_time, stRep.m_bidinfo.m_time);
		return updtime;
	}

	return updtime;
}

bool CBondContainer::GetBilateralfoById(int nID)
{
	class BilateralfoFinder : public CBondCompanyRep::ApplyCallback {
		bool		m_found;
	public:
		bool operator()(CBondCompanyRep* ptmp) {
			m_found = false;
			if (ptmp)
				ptmp->ApplyAccess(true, "", this);
			return m_found;
		}
		virtual bool DoAccess(const REPORT& rpt)
		{
			if (0 == atoi(rpt.m_company_id)) return true;//去掉交易所cfets报价
			if (strcmp(rpt.m_bidinfo.m_price_status, "0") == 0 || strcmp(rpt.m_askinfo.m_price_status, "0") == 0)
				return true;

			if (!IsEmpty(rpt.m_bidinfo.m_sPrice) && !IsEmpty(rpt.m_askinfo.m_sPrice))
			{
				m_found = true;
				return false;
			}
			return true;
		}
	};

	if (nID < 0 || nID >= GetSize())
		return false;

	CBondCompanyRep* ptmp = GetCompanyRep(nID);
	if (ptmp && ptmp->GetSize() > 0)
	{
		return BilateralfoFinder()(ptmp);
	}
	return false;
}

bool CBondContainer::IsBilateralfoById(const char* sCompanyID, int nID)
{
	class BilateralfoFinder : public CBondCompanyRep::ApplyCallback {
		bool		m_found;
		int			m_brokerId;
	public:
		BilateralfoFinder(int brokerId) :m_brokerId(brokerId) {};
		bool operator()(CBondCompanyRep* ptmp) {
			m_found = false;
			if (ptmp)
				ptmp->ApplyAccess(true, "", this);
			return m_found;
		}
		virtual bool DoAccess(const REPORT& rpt)
		{
			if (m_brokerId != atoi(rpt.m_company_id)) return true;//去掉交易所cfets报价
			if (strcmp(rpt.m_bidinfo.m_price_status, "0") == 0 || strcmp(rpt.m_askinfo.m_price_status, "0") == 0)
				return true;

			if (!IsEmpty(rpt.m_bidinfo.m_sPrice) && !IsEmpty(rpt.m_askinfo.m_sPrice))
			{
				m_found = true;
				return false;
			}
			return true;
		}
	};

	if (!sCompanyID || nID < 0 || nID >= GetSize())
		return false;

	CBondCompanyRep* ptmp = GetCompanyRep(nID);
	if (ptmp && ptmp->GetSize() > 0)
	{
		BilateralfoFinder finder(atoi(sCompanyID));
		return finder(ptmp);
	}
	return false;
}

bool CBondContainer::GetBilateralfoByIdOverSea(int nID)
{
	class BilateralfoOverseaFinder : public CBondCompanyRep::ApplyCallback {
		bool		m_found;
	public:
		bool operator()(CBondCompanyRep* ptmp) {
			m_found = false;
			if (ptmp)
				ptmp->ApplyAccess(true, "", this);
			return m_found;
		}
		virtual bool DoAccess(const REPORT& rpt)
		{
			if (rpt.m_price_sel == Indicative_Price)
			{
				if (strcmp(rpt.m_indx_info.m_symbol, "0") == 0 && !IsEmpty(rpt.m_indx_info.m_price))
				{
					m_found = true;
					return false;
				}
			}
			return true;
		}
	};

	if (nID < 0 || nID >= GetSize())
		return false;

	CBondCompanyRep* ptmp = GetCompanyRep(nID);
	if (ptmp && ptmp->GetSize() > 0)
	{
		return BilateralfoOverseaFinder()(ptmp);
	}
	return false;
}

bool CBondContainer::GetDiffenceById(const BLHCONDITION & Cond, int nID)
{
	class GetDiffenceByIdCallback : public CBondCompanyRep::ApplyCallback {
		bool			m_found;
		const char* m_diff_price;
	public:
		GetDiffenceByIdCallback(const char* diffPrice) :m_found(false), m_diff_price(diffPrice) {}
		bool IsFound()const { return m_found; }
		virtual bool DoAccess(const REPORT& quote)
		{
			if (strcmp(quote.m_bidinfo.m_sPrice, "Bid") == 0 || strcmp(quote.m_askinfo.m_sPrice, "Ofr") == 0)
				m_found = true;
			if (atof(m_diff_price) >= ((atof(quote.m_bidinfo.m_sPrice) - atof(quote.m_askinfo.m_sPrice)) * 100.00))
				m_found = true;
			return m_found ? false : true;
		}
	};

	if (nID < 0 || nID >= GetSize())
		return true;

	CBondCompanyRep* ptmp = GetCompanyRep(nID);
	if (ptmp && ptmp->GetSize() > 0)
	{
		GetDiffenceByIdCallback accessor(Cond.sDiffPrice);
		ptmp->ApplyAccess(true, "", &accessor);
		return accessor.IsFound();
	}
	return false;
}

bool CBondContainer::GetBankInfoById(const std::string &szKey, int nID, BKQUOTE& quote)
{
	if( nID<0 || nID>=GetSize())
        return false;
	memset(&quote, 0, sizeof(quote));
	CBondBankRep* ptmp = GetBankRep(nID);
	return ptmp?ptmp->GetBankRepByKey(szKey, quote):false;
}

void CBondContainer::ClearReport()
{
	BrokerRepMng->ClearReport();
	BankClientRepMng->ClearReport();
	BankRepMng->ClearReport();

	WRITELOCK(m_mutex);
	ClearVersion();
}

void CBondContainer::ClearReportLiquidation(LiquidationClearBestPrc clrFlag)
{
	HUGELOCK(m_mutex);
	int nSize = (int)m_vctbond.size();
	for (int i = 0; i < nSize; i++)//BIGLOOP
	{
		//后期按需分配内存，指针使用前需要进行判断
		CBondCompanyRep* cr = GetCompanyRep(i);
		if (cr) cr->ClearLiquidation(clrFlag);

		CBondBankRep* bnk = GetBankRep(i);
		if (bnk) bnk->Clear(clrFlag);

		CBondBankRep* clnt = GetClntRep(i);
		if (clnt) clnt->Clear(clrFlag);
	}
	ClearVersion(clrFlag);
}

void CBondContainer::ClearXCQuote()
{
	XCQuoteRepMng->ClearReport();
}

void CBondContainer::ClearCFETSQuote()
{
	CfetsRepMng->ClearReport();
}

void CBondContainer::ClearCFETSDealQuote()
{
	CfetsDealRepMng->ClearReport();
}

void CBondContainer::SetFreezeReport(const char * szCompanyID, bool bFreeze)
{
	class BkQuoteFreezeWriter :public CBondBankRep::ApplyCallback {
		bool			m_freeze;
	public:
		BkQuoteFreezeWriter(bool freeze) :m_freeze(freeze) {}
		virtual bool DoModify(BKQUOTE& quote)
		{
			if (m_freeze)
				quote.m_Freeze = Freeze_Price;
			else
				quote.m_Freeze = Normal_Price;
			return false;
		}
	};


	//冻结行情
	int nSize = (int)m_vctbond.size();
	for (int i = 0; i < nSize; i++)//BIGLOOP
	{
		CBondBankRep* pRep = GetClntRep(i);
		if (pRep)
		{
			BkQuoteFreezeWriter writer(bFreeze);
			pRep->ApplyModify(false, szCompanyID, &writer);
		}
	}
}


bool CBondContainer::SetMap( )
{
	HUGELOCK(m_mutex);

	m_map.RemoveAll();
	m_keymap.RemoveAll();

	int size = GetSize();
	int hash_capcity = qb::base::GetHashPrimeLargerThan(m_vctbond.capacity());
	m_map.InitHashTable(hash_capcity);
	m_keymap.InitHashTable(hash_capcity);

	if (size == 0)
		return true;
	for (int i = 0; i < size; i++)//BIGLOOP
	{
		const CBondInfo& info = ElementAtR(i);
		m_map.SetAt(info.GetCombBondCode(), (void*)i);
		m_keymap.SetAt(info.GetCombBondKey(), (void*)i);
	}
	return true;
}

bool CBondContainer::Clear( )
{
	BrokerRepMng->Clear();
	BankClientRepMng->Clear();
	BankRepMng->Clear();
	XCQuoteRepMng->Clear();
	CfetsRepMng->Clear();
	CfetsDealRepMng->Clear();

	HUGELOCK(m_mutex);

	for (int i = m_vctbond.size() - 1; i >= 0; --i)//BIGLOOP
	{
		if (m_vctbond[i] != nullptr)
		{
			//delete m_vctbond[i];
			m_vctbond[i] = nullptr;
		}
	}
	m_vctbond.clear();

		//增续发券相关信息
	for (int i = m_vctaddi.size() - 1; i >= 0; i--)//BIGLOOP
	{
		if (m_vctaddi[i] != nullptr) {
			delete m_vctaddi[i];
			m_vctaddi[i] = nullptr;
		}
	}

	m_vctaddi.clear();
	m_mapaddi.clear();
	m_map.RemoveAll();
	m_keymap.RemoveAll();
	return true;
}

bool CBondContainer::Remove(const char * combBondKey, bool isAddition)
{
	WRITELOCK(m_mutex);
	int nIndex = GetBondIndexImpl(combBondKey);
	if (nIndex >= 0 && nIndex<GetSizeImpl())
	{
		CBondInfo& info = ElementAtW(nIndex);
		if (!isAddition)
		{
			//LOGDEBUG("[DICT]Not Additional Bond Dict");
			if (info.IsAddIssueBond())
			{
				//LOGDEBUG("[DICT]Additional Bond, cannot Remove");
				return false;//非增续发字典删除时，判定：如果是增续发券，保留
			}
			else
			{
				//LOGDEBUG("[DICT]Not Additional Bond, Remove");
			}
		}
		else
		{
			//LOGDEBUG("[DICT]Additional Bond Dict, Remove");
		}
		//LOGDEBUG("[DICT]Removed");
		info.SetValidity(false);
		return true;
	}
	return false;
}
bool CBondContainer::Remove(const char * szKey, const char* szMarket, bool isAddition)
{
	WRITELOCK(m_mutex);
	int nIndex = GetBondIndex(szKey,szMarket);
	if (nIndex >= 0 && nIndex < GetSizeImpl())
	{
		CBondInfo& info = ElementAtW(nIndex);
		if (!isAddition)
		{
			//LOGDEBUG("[DICT]Not Additional Bond Dict");
			if (info.IsAddIssueBond())
			{
				//LOGDEBUG("[DICT]Additional Bond, cannot Remove");
				return false;//非增续发字典删除时，判定：如果是增续发券，保留
			}
			else
			{
				//LOGDEBUG("[DICT]Not Additional Bond, Remove");
			}
		}
		else
		{
			//LOGDEBUG("[DICT]Additional Bond Dict, Remove");
		}
		//LOGDEBUG("[DICT]Removed");
		info.SetValidity(false);
		return true;
	}
	return false;
}

void CBondContainer::ClearCDCDataAll()
{
	CBondCDCPriceInfo::instance().ClearAll();
}

void CBondContainer::ClearCDCData(bool bSpecial)
{
	if (bSpecial)
		CBondCDCPriceInfo::instance().ClearSpecial();
	else
		CBondCDCPriceInfo::instance().ClearNonSpecial();
}

void CBondContainer::ClearCSData()
{
	CBondCSInfo::instance().clear();
}


void CBondContainer::CalcRemainingDate(time_t t)
{
	static std::mutex s_lock;
	bool isFirst = false;
	{
		std::lock_guard<std::mutex> m_locker(s_lock);
		isFirst = m_nLastCalcDate == 0;
		int lastCalcDate = 0;
		struct tm* tt = localtime(&t);
		if (tt)
			lastCalcDate = (tt->tm_year + 1900) * 10000 + (tt->tm_mon + 1) * 100 + tt->tm_mday;
		if (lastCalcDate == m_nLastCalcDate)
			return;
		m_nLastCalcDate = lastCalcDate;
	}
	
	//MEM_METRIC("CalcRemainingDate");
	log_begin();
	{
		using qb::base::os::fmtstr;
		std::vector<int> abonds, absBonds;
		int nPass = 0, nSecond = 0, nSize = 0;
		const char* expired_str = strBondLib_Expired();/*"已到期"*//*"已到期"*/
		{
			HUGELOCK(m_mutex);
			nSize = GetSize();
			abonds.reserve(nSize);
			absBonds.reserve(nSize);

			int Today = 0;
			if (t > 0)
			{
				struct tm *tmNow = localtime(&t);
				Today = (tmNow->tm_year + 1900) * 10000 + (tmNow->tm_mon + 1) * 100 + tmNow->tm_mday;
			}
			for (int i = 0; i < nSize; i++)//BIGLOOP
			{
				CBondInfo& info = ElementAtW(i);
				if (info.IsValidBond())
				{
					/*	原先逻辑是:对所有有效债券(非空的BondKey),重新计算其剩余期限字段(两个)
						现在更改为:只针对未过期的债券,才重新计算器剩余期限字段(两个)
						对于已经过期的券,CBondInfoDebug::GetRemainPeriod中返回过期字符串	*/
					if (strcmp(expired_str, info.GetRemainPeriod(Today)) != 0)
					{
						// 之前计算没有过期,现在按照现在时间,再来计算看是否过期
						if(!isFirst)
							info.SetRemainDate("");
						if (isFirst || strcmp(expired_str, info.GetRemainPeriod(Today)) != 0)
						{
							nSecond++;
							abonds.push_back(i);
							if (!info.IsExchange() && info.IsBondABS())
								absBonds.push_back(i);
						}
						else
						{
							nPass++;
						}
					}
					else
					{
						nPass++;
					}
				}
			}
		}
		//timer.AddStep(fmtstr("总数量:%6d 过期:%6d 二次计算:%6d", nSize, nPass, nSecond));


		int absCount = absBonds.size();
		vector<int> abondsCopy = abonds;
		//timer.AddStep("拷贝vector<int>");

		CSSVContainer::availableBond().SetDataSafe(std::move(abonds));
		CSSVContainer::availableAbsBond().SetDataSafe(std::move(absBonds));

		//更新交易所有效债券
		vector<int> exBonds;
		exBonds.reserve(abondsCopy.size());
		for (int i = 0; i < abondsCopy.size(); ++i)
		{
			if (ElementAtR(abondsCopy[i]).IsExchange())
				exBonds.push_back(abondsCopy[i]);
		}
		int exCount = exBonds.size();
		CSSVContainer::availableExBond().SetDataSafe(std::move(exBonds));
		//timer.AddStep(fmtstr("更新AfxGetExchangeBond:%d", exCount));
	}
	log_end();
	DumpStatus();
}

void CBondContainer::CalcBondExpireInHoliday()
{
	CBondCalendar& cal = CBondCalendar::instance();
	HUGELOCK(m_mutex);
	int nSize = GetSize();
	for (int i = 0; i < nSize; i++)//BIGLOOP
	{
		CBondInfo& info = ElementAtW(i);
		if (info.IsValidBond() && strcmp(info.GetRemainDate(), strBondLib_Expired()/*"已到期"*/) != 0) {
			int nDate = atoi(info.GetMaturityDate());
			if (cal.IsHoliday("CNY", "CIB", nDate))info.SetExpireInHoliday(true);
			else if (cal.IsHoliday("CNY", "SSE", nDate))info.SetExpireInHoliday(true);
			else info.SetExpireInHoliday(false);
		}
	}
}

int	CBondContainer::GetLastCalcDate(){
	return m_nLastCalcDate;
}

double CBondContainer::CalcRemainingDay(const std::string& period, bool ytm)
{
	const char* sPeriod = period.c_str();
	if (sPeriod == 0 || *sPeriod == '\0')
		return -1;
	// 原始逻辑
	// 截取+之前的部分,如果没有,取整个部分
	// 将末尾的空白字符移除
	// 取末尾字符为YMD
	// 将开头字符串转化为整数
	// 格式: \d+[YMD]\s*\+?
	// 性能测试结果:优化编译12-15倍,不优化编译7倍
	// 性能和单元测试见本路径的CalcRemainingDay_UnitTest.cpp,
	// 测试工程见QBBrowser\UnitTest\UnitTest.vcxproj
	// 实现需要使用CalcRemainingDay_UnitTest.cpp中的RemainingDayCollector收集采样数据
	static double ten[8] = { 1, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001 };
	const char* pstr = sPeriod;	// 
	double result = INVALID_CDC_VALUE;
	auto is_plus = [](const char schar) {return schar == '+'; };
	int round = ytm ? (std::count_if(period.begin(), period.end(), is_plus)) : 0;
	if (round < 0) round = 0;
	for (auto roundNum = 0; roundNum <= round; ++roundNum)
	{
		if (*pstr == '\0') break;
		int num1 = 0, num2 = 0;
		int num_count = 0;		// 开头是数字的个数
		int bit = 0;
		bool dot = false;
		bool num_mode = true;		// 开始必须是数字模式
		int ncount = 0;		// 设定单位之后出现非blank的字符串个数
		char unit = 0;		// 必须设定
		while (*pstr != '\0' && *pstr != '+')
		{
			char c = *pstr++;
			if (num_mode)
			{
				if ((c >= '0' && c <= '9') || c == '.')
				{
					if (c == '.')	dot = true;
					else if (!dot)	num1 = (num1 << 3) + (num1 << 1) + (c - '0');
					else {
						num2 = (num2 << 3) + (num2 << 1) + (c - '0'); bit++;
					}
					num_count++;
				}
				else if (num_count <= 0)
					break;
				else
					num_mode = false;
			}
			if (!num_mode)
			{
				if (c == 'Y' || c == 'M' || c == 'D')
				{
					unit = c;
					ncount = 0;
				}
				else if (c != ' ')
				{
					unit = 0;
					ncount++;
				}
			}
		}

		if (num_count > 0 && unit != 0 && ncount <= 0)
		{
			double u = (unit == 'Y') ? 365 : (unit == 'M' ? 30.01 : 1);
			double dTmp = bit < 8 ? (u * (num1 + num2 * ten[bit])) : atof(sPeriod) * u;
			result = (result == INVALID_CDC_VALUE) ? dTmp : result + dTmp;

		}
		if (!ytm) break;//如果未到期
		while (*pstr != '\0') //去除加号和空格
		{
			char c = *pstr;
			if ((c >= '0' && c <= '9') || c == '.')
			{
				break;
			}
			pstr++;
		}

	}

	return (result == INVALID_CDC_VALUE) ? -999 : result;
}

bool CBondContainer::UpadateBondList(const BLHCONDITION & condStr,SSIntVector& vct_result,
									 SSIntVector& vct_resdel,const std::list<xQBBondQuote_c> &bclist, bool bSecondaryMarket )
{
	int i = 0;
	READLOCK(m_mutex);
	if( condStr.isAllin() )
	{
		std::list<xQBBondQuote_c>::const_iterator itor = bclist.begin();
		for (;itor!=bclist.end();itor++)
		{
			bool bAdd = false;
			bAdd = GetBondInfoByKey(itor->m_BondKey,itor->m_ListedMarket,nullptr,&i);
			if(strcmp(itor->m_BidStatus,"0")==0||strcmp(itor->m_OfrStatus,"0")==0)
				vct_resdel.m_vct.push_back(i);
			else if(bAdd)vct_result.m_vct.push_back(i);
		}
	}
	else
	{
		BrokerKey brokerkey;
		int	nCount	=	0;
		std::list<xQBBondQuote_c>::const_iterator itor = bclist.begin();
		for (;itor!=bclist.end();itor++)
		{
			int bondIndex = GetBondIndex(itor->m_BondKey, itor->m_ListedMarket);
			if (!IsValidIndex(bondIndex))continue;
			const CBondInfo& info = ElementAtR(bondIndex);

			bool bContinue = true;
			CBondBankRep* prep = nullptr;
			if( bContinue && condStr.nBothFlg != 0 && !IsBilateralPrice(condStr,i) )
				bContinue = false;
			if( bContinue && condStr.nNewFlg != 0 && !info.IsNewBond() )
				bContinue = false;
			if( bContinue && condStr.nHasFlg != 0 && !IsHasPrice(condStr,i) )
				bContinue = false;
			if( bContinue && condStr.nMatFlg != 0 && GetMaturityBond(info) )
				bContinue = false;
			if( bContinue && condStr.nASemi != 0 && GetRebateBond(info) )
				bContinue = false;
			if( bContinue && condStr.nMortgt != 0 && !info.IsMortgage() )
				bContinue = false;
			if( bContinue && condStr.nCrosmk != 0 && !info.IsCrossMarket() )
				bContinue = false;
			if( bContinue && condStr.nEntrTyp != 0 && !GetSOEenterType(condStr,info) )
				bContinue = false;
			if( bContinue && condStr.nOffset != 0 && !GetBondOffsetEstPrc(condStr,i) )
				bContinue = false;
			if( bContinue && !IsEmpty(condStr.sDiffPrice) && !GetDiffPrice(condStr,i) )
				bContinue = false;
			if (bContinue && (!IsEmpty(condStr.sBPrice) || !IsEmpty(condStr.sBPriceEnd)) && !GetBidCndPrice(condStr, i))
				bContinue = false;
			if (bContinue && (!IsEmpty(condStr.sOPrice) || !IsEmpty(condStr.sOPriceEnd)) && !GetOfrCndPrice(condStr, i))
				bContinue = false;
			if( bContinue && condStr.nCommonUse[0] != CBondContainer::CommAll && !info.CheckCommonUseType(condStr)) //常用
				bContinue = false;
			if( bContinue && condStr.nType[0] != BondAll && !info.CheckBondType(condStr))
				bContinue = false;
			if( bContinue && condStr.nIssuerRating[0] != RatingAll && !GetMultiLevel(condStr,info))
				bContinue = false;

			if (bContinue && condStr.nOutlookRating[0] != OutlookRatingAll && !GetOutlookRatingLevel(condStr, info))
				bContinue = false;

			if (bContinue && condStr.nCDCRating[0] != CDCRatingAll && !GetCDCRatingLevel(condStr, info))
				bContinue = false;
			if (bContinue && condStr.nCSIRating[0] != CSIRatingAll && !GetCSIRatingLevel(condStr, info))
				bContinue = false;
			if (bContinue && condStr.nCBRRating[0] != CBRRatingAll && !GetCBRRatingLevel(condStr, info))
				bContinue = false;

			if( bContinue && condStr.nWarrant[0] != WarrAll && !GetWarrType(condStr,info))
				bContinue = false;
			if( bContinue && condStr.nCouponType[0] != CouponAll && !GetMultiCouponType(condStr,info))
				bContinue = false;
			if( bContinue && condStr.nRight != RightAll && GetRightType(condStr.nRight) != info.IsRight())
				bContinue = false;
			if( bContinue && condStr.nRange[0] != RangeAll && !GetMaturityRange(condStr,info,bSecondaryMarket ) )
				bContinue = false;
			if( bContinue && condStr.nMunicp[0] != MunicAll && !GetMunicpType(condStr,info))
				bContinue = false;
			if( bContinue && condStr.nInterbank != 0 && !info.IsInterbank())
				bContinue = false;
			if( bContinue && condStr.nExchange != 0 && !info.IsExchange())
				bContinue = false;
			if( bContinue && condStr.nInstion[0] != InstAll && !GetMultiInstion(condStr,info))
				bContinue = false;
			if( bContinue && condStr.szIssuer[0][0] != '\0' && !info.CheckIssuer(condStr))
				bContinue = false;
			if( bContinue && condStr.szSector[0][0] != '\0' && !info.CheckSector(condStr))
				bContinue = false;
			if (bContinue && condStr.szSector2021[0][0] != '\0' && !info.CheckSector2021(condStr))
				bContinue = false;
			if( bContinue && condStr.szArea[0][0] != '\0' && !info.CheckArea(condStr))
				bContinue = false;
			if( bContinue && condStr.szSubType[0][0] != '\0' && !info.CheckBontSubType(condStr))
				bContinue = false;
			if( bContinue && condStr.nDebtRating[0] != DRatingNone && !info.CheckDebtRating(condStr))
				bContinue = false;
			if( bContinue && condStr.nFinDebt[0] != FinDebtNone && !info.CheckFinDebt(condStr))
				bContinue = false;
			if (bContinue && condStr.nPlatform[0] != PlatforamAll && !IsPlatformType(condStr, info))//平台债
				bContinue = false;
			if (bContinue && condStr.nLocalBond[0] != LocalBondAll && !IsLocalBond(condStr, info))//地方债
				bContinue = false;
			// add  by lbl  NCD  
			if (bContinue && condStr.nNCDRating[0] != NCDRatingAll && !info.CheckNCDRating(condStr))//NCD
				bContinue = false;
			// end 
			if( bContinue && condStr.nIssueYear[0] != 0 && !info.CheckIssueYear(condStr))
				bContinue = false;
			if (bContinue && condStr.nExpireInHoliday == 1 && info.IsExpireInHoliday())//不含假期
				bContinue = false;

			//if(strcmp(itor->m_BidStatus,"-1")==0&&strcmp(itor->m_OfrStatus,"-1")==0)
			//	vct_resdel.m_vct.push_back(i);
			if(bContinue)vct_result.m_vct.push_back(i);
			else vct_resdel.m_vct.push_back(i);
		}
	}

	return true;
}

bool CBondContainer::UpdateContainer(BLHCONDITION & condStr,SSBrokerKeyVector& vct_result,
									 SSBrokerKeyVector& vct_resdel,const std::list<xQBBestPriceUnit_c> &qblist, bool bSecondaryMarket )
{
	// 底层会改写condStr的sCompanyid字段,因此condStr不能是const
	READLOCK(m_mutex);
	if( condStr.isAllin())
	{
		std::list<xQBBestPriceUnit_c>::const_iterator itor = qblist.begin();
		for (;itor!=qblist.end();itor++)
		{
			bool bAdd = false,bGiveup=false;
			BrokerKey brokerkey;
			int bondIndex = GetBondIndex(itor->m_bondkey,itor->m_listedmarket);
			if (!IsValidIndex(bondIndex))continue;
			brokerkey.m_nIndex = bondIndex; 
			brokerkey.SetBrokerId(itor->m_company_id);

			if(strcmp(itor->m_price_status,"0")==0)
			{
				vct_resdel.m_vct.push_back(brokerkey);
			}
			else if(bAdd)
			{
				vct_result.m_vct.push_back(brokerkey);
			}
			else
			{
				bGiveup = true;
			}

			if(!bGiveup)
				NETLOG("%s has been pushed --> %s, ver = %d",itor->m_bond_shorname,bAdd?"vct_result":"vct_resdel", itor->m_version);
			else
				NETLOG("%s has been gived up, ver = %d",itor->m_bond_shorname, itor->m_version);
		}
	}
	else
	{
		bool HasRatingRightsOfCDC = true;// AfxGetUserAccountManager().HasAuthOfCDC();
		bool HasRatingRightsOfCSI = true;// AfxGetUserAccountManager().HasAuthOfCSI();
		bool HasRatingRightsOfCBR = true;// AfxGetUserAccountManager().HasAuthOfCBR();

		BrokerKey brokerkey;
		int	nCount	=	0;
		std::list<xQBBestPriceUnit_c>::const_iterator itor = qblist.begin();
		for (;itor!=qblist.end();itor++)
		{
			int bondIndex = GetBondIndex(itor->m_bondkey, itor->m_listedmarket);
			if (!IsValidIndex(bondIndex))continue;
			const CBondInfo& info = ElementAtR(bondIndex);
			
			brokerkey.Clear();	
			FIELDCOPY( condStr.sCompanyid,itor->m_company_id); //用自身的brokerid过滤，20150901
			bool bContinue = false;
			do {
				if (condStr.nBothFlg != 0 && !IsBilateralPrice(condStr, bondIndex))
					break;
				if (condStr.nNewFlg != 0 && !info.IsNewBond())
					break;
				if (condStr.nHasFlg != 0 && !IsHasPrice(condStr, bondIndex))
					break;
				if (condStr.nMatFlg != 0 && GetMaturityBond(info))
					break;
				if (condStr.nASemi != 0 && GetRebateBond(info))
					break;
				if (condStr.nMortgt != 0 && !info.IsMortgage())
					break;
				if (condStr.nCrosmk != 0 && !info.IsCrossMarket())
					break;
				if (condStr.nEntrTyp != 0 && !GetSOEenterType(condStr, info))
					break;
				if (condStr.nOffset != 0 && !GetBondOffsetEstPrc(condStr, bondIndex))
					break;
				if (condStr.nSettlement[0] != CBondContainer::StmAll && !CheckSettlement(condStr, bondIndex))
					break;
				if (!IsEmpty(condStr.sDiffPrice) && !GetDiffPrice(condStr, bondIndex))
					break;
				if ((!IsEmpty(condStr.sBPrice) || !IsEmpty(condStr.sBPriceEnd)) && !GetBidCndPrice(condStr, bondIndex))
					break;
				if ((!IsEmpty(condStr.sOPrice) || !IsEmpty(condStr.sOPriceEnd)) && !GetOfrCndPrice(condStr, bondIndex))
					break;
				if ((!IsEmpty(condStr.sOPrice) || !IsEmpty(condStr.sOPriceEnd)) && !GetOfrCndPrice(condStr, bondIndex))
					break;
				if (condStr.nCommonUse[0] != CBondContainer::CommAll && !info.CheckCommonUseType(condStr)) //常用
					break;
				if (condStr.nType[0] != BondAll && !info.CheckBondType(condStr))
					break;
				if (condStr.nIssuerRating[0] != RatingAll && !GetMultiLevel(condStr, info))
					break;
				if (condStr.nOutlookRating[0] != OutlookRatingAll && !GetOutlookRatingLevel(condStr, info))
					break;
				if (HasRatingRightsOfCDC &&	condStr.nCDCRating[0] != CDCRatingAll && !GetCDCRatingLevel(condStr, info))
					break;
				if (HasRatingRightsOfCSI &&	condStr.nCSIRating[0] != CSIRatingAll && !GetCSIRatingLevel(condStr, info))
					break;
				if (HasRatingRightsOfCBR &&	condStr.nCBRRating[0] != CBRRatingAll && !GetCBRRatingLevel(condStr, info))
					break;
				if (condStr.nWarrant[0] != WarrAll && !GetWarrType(condStr, info))
					break;
				if (condStr.nCouponType[0] != CouponAll && !GetMultiCouponType(condStr, info))
					break;
				if (condStr.nRight != RightAll && GetRightType(condStr.nRight) != info.IsRight())
					break;
				if (condStr.nRightEx[0] != RightExAll && !info.CheckRightEx(condStr))
					break;
				if (condStr.nRange[0] != RangeAll && !GetMaturityRange(condStr, info, bSecondaryMarket))
					break;
				if (condStr.nMunicp[0] != MunicAll && !GetMunicpType(condStr, info))
					break;
				if (condStr.nInterbank != 0 && !info.IsInterbank())
					break;
				if (condStr.nExchange != 0 && !info.IsExchange())
					break;
				if (condStr.nInstion[0] != InstAll && !GetMultiInstion(condStr, info))
					break;
				if (condStr.szIssuer[0][0] != '\0' && !info.CheckIssuer(condStr))
					break;
				if (condStr.szGuarantor[0][0] != '\0' && !info.CheckGuarantor(condStr))
					break;
				if (condStr.szSector[0][0] != '\0' && !info.CheckSector(condStr))
					break;
				if (condStr.szSector2021[0][0] != '\0' && !info.CheckSector2021(condStr))
					break;
				if (condStr.szArea[0][0] != '\0' && !info.CheckArea(condStr))
					break;
				if (condStr.szSubType[0][0] != '\0' && !info.CheckBontSubType(condStr))
					break;
				if (condStr.nDebtRating[0] != DRatingNone && !info.CheckDebtRating(condStr))
					break;
				if (condStr.nFinDebt[0] != FinDebtNone && !info.CheckFinDebt(condStr))
					break;
				if (condStr.nPlatform[0] != PlatforamAll && !IsPlatformType(condStr, info))//平台债
					break;
				if (condStr.nLocalBond[0] != LocalBondAll && !IsLocalBond(condStr, info))//地方债
					break;
				if (condStr.nNCDRating[0] != NCDRatingAll && !info.CheckNCDRating(condStr))//NCD , add  by lbl  NCD  
					break;
				if (condStr.nIssueYear[0] != 0 && !info.CheckIssueYear(condStr))//发行年份
					break;
				if (!IsEmpty(condStr.sVolBid) && !GetVolBidCompare(condStr, bondIndex)) //vol.bid
					break;
				if (!IsEmpty(condStr.sVolOfr) && !GetVolOfrCompare(condStr, bondIndex)) //vol.ofr
					break;
				if (condStr.nExchangeType != CBondContainer::kExchAll && !GetExchangeType(condStr, info))		//交易所类型
					break;
				if (condStr.nETSBond[0] != CBondContainer::ETSBondAll && !IsETSBondType(condStr, info))	 //永续债
					break;
				if (condStr.nCorpBond[0] != CBondContainer::CorpBondAll && !IsCorpBondType(condStr, info))	 //公司债
					break;
				if (condStr.nAssetStatus[0] != CBondContainer::AssetAll && !info.CheckAssetStatus(condStr))//发行
					break;
				if (!IsEmpty(condStr.sBidCdc) && !GetBidCdcCompare(condStr, bondIndex)) //bid-中债
					break;
				if (!IsEmpty(condStr.sCdcOfr) && !GetCdcOfrCompare(condStr, bondIndex)) //中债-ofr
					break;
				if (condStr.nExpireInHoliday == 1 && info.IsExpireInHoliday())//不含假期
					break;
				bContinue = true;
			}while (0);
			brokerkey.m_nIndex = bondIndex; brokerkey.SetBrokerId(itor->m_company_id);

			if(!bContinue)
				vct_resdel.m_vct.push_back(brokerkey);
			else
				vct_result.m_vct.push_back(brokerkey);

			NETLOG("%s has been pushed --> vct_result, ver = %d",itor->m_bond_shorname,bContinue?"vct_result":"vct_resdel",itor->m_version);
		}
	}

	return true;
}


bool CBondContainer::UpdateContainerBySSEFI(BLHCONDITION & condStr, SSBrokerKeyVector& vct_result,
	SSBrokerKeyVector& vct_resdel, const std::list<xQBBestPriceUnit_c> &qblist, bool bSecondaryMarket)
{
	// 底层会改写condStr的sCompanyid字段,因此condStr不能是const
	READLOCK(m_mutex);

	BrokerKey brokerkey;
	int	nCount = 0;
	std::list<xQBBestPriceUnit_c>::const_iterator itor = qblist.begin();
	for (; itor != qblist.end(); itor++)
	{
		int bondIndex = GetBondIndex(itor->m_bondkey, itor->m_listedmarket);
		if (!IsValidIndex(bondIndex))continue;

		brokerkey.Clear();
		const CBondInfo& info = ElementAtR(bondIndex);
		if (strcmp(info.GetListedMarket(), "SSE") != 0)continue;
		FIELDCOPY(condStr.sCompanyid, itor->m_company_id); //用自身的brokerid过滤，20150901
		bool bContinue = false;
		do {
			if (condStr.nBothFlg != 0 && !IsBilateralPrice(condStr, bondIndex))
				break;
			if (condStr.nNewFlg != 0 && !info.IsNewBond())
				break;
			if (condStr.nHasFlg != 0 && !IsHasPrice(condStr, bondIndex))
				break;
			if (condStr.nMatFlg != 0 && GetMaturityBond(info))
				break;
			if (condStr.nASemi != 0 && GetRebateBond(info))
				break;
			if (condStr.nMortgt != 0 && !info.IsMortgage())
				break;
			if (condStr.nCrosmk != 0 && !info.IsCrossMarket())
				break;
			if (condStr.nEntrTyp != 0 && !GetSOEenterType(condStr, info))
				break;
			if (condStr.nOffset != 0 && !GetBondOffsetEstPrc(condStr, bondIndex))
				break;
			if (!IsEmpty(condStr.sDiffPrice) && !GetDiffPrice(condStr, bondIndex))
				break;
			if (!IsEmpty(condStr.sBPrice) && !GetBidCndPrice(condStr, bondIndex))
				break;
			if (condStr.nCommonUse[0] != CBondContainer::CommAll && !info.CheckCommonUseType(condStr)) //常用
				break;
			if (!IsEmpty(condStr.sOPrice) && !GetOfrCndPrice(condStr, bondIndex))
				break;
			if (condStr.nType[0] != BondAll && !info.CheckBondTypeV2(condStr))
				break;
			if (condStr.nIssuerRating[0] != RatingAll && !GetMultiLevel(condStr, info))
				break;
			if (condStr.nWarrant[0] != WarrAll && !GetWarrType(condStr, info))
				break;
			if (condStr.nCouponType[0] != CouponAll && !GetMultiCouponType(condStr, info))
				break;
			if (condStr.nRight != RightAll && GetRightType(condStr.nRight) != info.IsRight())
				break;
			if (condStr.nRightEx[0] != RightExAll && !info.CheckRightEx(condStr))
				break;
			if (condStr.nRange[0] != RangeAll && !GetMaturityRange(condStr, info, bSecondaryMarket))
				break;
			if (condStr.nMunicp[0] != MunicAll && !GetMunicpType(condStr, info))
				break;
			if (condStr.nInterbank != 0 && !info.IsInterbank())
				break;
			if (condStr.nExchange != 0 && !info.IsExchange())
				break;
			if (condStr.nInstion[0] != InstAll && !GetMultiInstion(condStr, info))
				break;
			if (condStr.szIssuer[0][0] != '\0' && !info.CheckIssuer(condStr))
				break;
			if (condStr.szSector[0][0] != '\0' && !info.CheckSector(condStr))
				break;
			if (condStr.szSector2021[0][0] != '\0' && !info.CheckSector2021(condStr))
				break;
			if (condStr.szArea[0][0] != '\0' && !info.CheckArea(condStr))
				break;
			if (condStr.szSubType[0][0] != '\0' && !info.CheckBontSubType(condStr))
				break;
			if (condStr.nDebtRating[0] != DRatingNone && !info.CheckDebtRating(condStr))
				break;
			if (condStr.nFinDebt[0] != FinDebtNone && !info.CheckFinDebt(condStr))
				break;
			if (condStr.nPlatform[0] != PlatforamAll && !IsPlatformType(condStr, info))//平台债
				break;
			if (condStr.nLocalBond[0] != LocalBondAll && !IsLocalBond(condStr, info))//地方债
				break;
			if (condStr.nNCDRating[0] != NCDRatingAll && !info.CheckNCDRating(condStr))//add  by lbl  NCD  			
				break;
			if (condStr.nIssueYear[0] != 0 && !info.CheckIssueYear(condStr))
				break;
			if (!IsEmpty(condStr.sVolBid) && !GetVolBidCompare(condStr, bondIndex)) //vol.bid
				break;
			if (!IsEmpty(condStr.sVolOfr) && !GetVolOfrCompare(condStr, bondIndex)) //vol.ofr
				break;
			if (condStr.nExchangeType != CBondContainer::kExchAll && !GetExchangeType(condStr, info))		//交易所类型
				break;
			if (condStr.nETSBond[0] != CBondContainer::ETSBondAll && !IsETSBondType(condStr, info))	 //永续债
				break;
			if (condStr.nCorpBond[0] != CBondContainer::CorpBondAll && !IsCorpBondType(condStr, info))	 //公司债
				break;
			if (condStr.nAssetStatus[0] != CBondContainer::AssetAll && !info.CheckAssetStatus(condStr))//发行
				break;
			if (!IsEmpty(condStr.sBidCdc) && !GetBidCdcCompare(condStr, bondIndex)) //bid-中债
				break;
			if (!IsEmpty(condStr.sCdcOfr) && !GetCdcOfrCompare(condStr, bondIndex)) //中债-ofr
				break;
			if (condStr.nExpireInHoliday == 1 && info.IsExpireInHoliday())//不含假期
				break;
			bContinue = true;
		} while (0);
		brokerkey.m_nIndex = bondIndex; brokerkey.SetBrokerId(itor->m_company_id);

		if (!bContinue){
			vct_resdel.m_vct.push_back(brokerkey);
		}
		else{
			vct_result.m_vct.push_back(brokerkey);
		}
		NETLOG("%s has been pushed --> vct_result, ver = %d", itor->m_bond_shorname, bContinue ? "vct_result" : "vct_resdel", itor->m_version);
	}

	return true;
}


bool CBondContainer::UpdateContainerByABSBond(BLHCONDITION & condStr, SSBrokerKeyVector& vct_result,
	SSBrokerKeyVector& vct_resdel, const std::list<xQBBestPriceUnit_c> &qblist, bool bSecondaryMarket)
{

	return true;
}

bool CBondContainer::UpdateOverSeaContainer(const BLHCONDITION & condStr,SSBrokerKeyVector& vct_result,
											SSBrokerKeyVector& vct_resdel,const std::list<xQBIndicativePriceUnit_c> &qblist, bool bSecondaryMarket )
{
	READLOCK(m_mutex);
	if( condStr.isAllin()){
		std::list<xQBIndicativePriceUnit_c>::const_iterator itor = qblist.begin();
		for (;itor!=qblist.end();itor++)
		{
			bool bAdd = false;
			BrokerKey brokerkey;
			int bondIndex = GetBondIndex(itor->m_bondkey, itor->m_listedmarket);
			brokerkey.m_nIndex = bondIndex; brokerkey.SetBrokerId(itor->m_company_id);
			if(IsEmpty(itor->m_price))
				vct_resdel.m_vct.push_back(brokerkey);
			else if(bAdd)vct_result.m_vct.push_back(brokerkey);
		}
	}
	else
	{
		BrokerKey brokerkey;
		int	nCount	=	0;
		std::list<xQBIndicativePriceUnit_c>::const_iterator itor = qblist.begin();
		for (;itor!=qblist.end();itor++)
		{
			int bondIndex = GetBondIndex(itor->m_bondkey, itor->m_listedmarket);
			if (!IsValidIndex(bondIndex))continue;
			const CBondInfo& info = ElementAtR(bondIndex);

			bool bContinue = true;
			brokerkey.Clear();

			if( bContinue && condStr.nBothFlg != 0 && !IsBilateralPrice(condStr,bondIndex) )
				bContinue = false;
			if( bContinue && condStr.nNewFlg != 0 && !info.IsNewBond() )
				bContinue = false;
			if( bContinue && condStr.nHasFlg != 0 && !IsHasPrice(condStr,bondIndex) )
				bContinue = false;
			if( bContinue && condStr.nMatFlg != 0 && GetMaturityBond(info) )
				bContinue = false;
			if( bContinue && condStr.nASemi != 0 && GetRebateBond(info) )
				bContinue = false;
			if( bContinue && condStr.nMortgt != 0 && !info.IsMortgage() )
				bContinue = false;
			if( bContinue && condStr.nCrosmk != 0 && !info.IsCrossMarket() )
				bContinue = false;
			if( bContinue && condStr.nEntrTyp != 0 && !GetSOEenterType(condStr,info) )
				bContinue = false;
			if( bContinue && condStr.nOffset != 0 && !GetBondOffsetEstPrc(condStr,bondIndex) )
				bContinue = false;
			if( bContinue && !IsEmpty(condStr.sDiffPrice) && !GetDiffPrice(condStr,bondIndex) )
				bContinue = false;
			if (bContinue && (!IsEmpty(condStr.sBPrice) || !IsEmpty(condStr.sBPriceEnd)) && !GetBidCndPrice(condStr, bondIndex))
				bContinue = false;
			if (bContinue && (!IsEmpty(condStr.sOPrice) || !IsEmpty(condStr.sOPriceEnd)) && !GetOfrCndPrice(condStr, bondIndex))
				bContinue = false;
			if( bContinue && condStr.nCommonUse[0] != CBondContainer::CommAll && !info.CheckCommonUseType(condStr)) //常用
				bContinue = false;
			if( bContinue && condStr.nType[0] != BondAll && !info.CheckBondType(condStr))
				bContinue = false;
			if( bContinue && condStr.nIssuerRating[0] != RatingAll && !GetMultiLevel(condStr,info))
				bContinue = false;

			if (bContinue && condStr.nOutlookRating[0] != OutlookRatingAll && !GetOutlookRatingLevel(condStr, info))
				bContinue = false;

			if (bContinue && condStr.nCDCRating[0] != CDCRatingAll && !GetCDCRatingLevel(condStr, info))
				bContinue = false;
			if (bContinue && condStr.nCSIRating[0] != CSIRatingAll && !GetCSIRatingLevel(condStr, info))
				bContinue = false;
			if (bContinue && condStr.nCBRRating[0] != CBRRatingAll && !GetCBRRatingLevel(condStr, info))
				bContinue = false;

			if( bContinue && condStr.nWarrant[0] != WarrAll && !GetWarrType(condStr,info))
				bContinue = false;
			if( bContinue && condStr.nCouponType[0] != CouponAll && !GetMultiCouponType(condStr,info))
				bContinue = false;
			if( bContinue && condStr.nRight != RightAll && GetRightType(condStr.nRight) != info.IsRight())
				bContinue = false;
			if( bContinue && condStr.nRange[0] != RangeAll && !GetMaturityRange(condStr,info,bSecondaryMarket ) )
				bContinue = false;
			if( bContinue && condStr.nMunicp[0] != MunicAll && !GetMunicpType(condStr,info))
				bContinue = false;
			if( bContinue && condStr.nInterbank != 0 && !info.IsInterbank())
				bContinue = false;
			if( bContinue && condStr.nExchange != 0 && !info.IsExchange())
				bContinue = false;
			if( bContinue && condStr.nInstion[0] != InstAll && !GetMultiInstion(condStr,info))
				bContinue = false;
			if( bContinue && condStr.szIssuer[0][0] != '\0' && !info.CheckIssuer(condStr))
				bContinue = false;
			if( bContinue && condStr.szSector[0][0] != '\0' && !info.CheckSector(condStr))
				bContinue = false;
			if (bContinue && condStr.szSector2021[0][0] != '\0' && !info.CheckSector2021(condStr))
				bContinue = false;
			if( bContinue && condStr.szArea[0][0] != '\0' && !info.CheckArea(condStr))
				bContinue = false;
			if( bContinue && condStr.szSubType[0][0] != '\0' && !info.CheckBontSubType(condStr))
				bContinue = false;
			if( bContinue && condStr.nDebtRating[0] != DRatingNone && !info.CheckDebtRating(condStr))
				bContinue = false;
			if( bContinue && condStr.nFinDebt[0] != FinDebtNone && !info.CheckFinDebt(condStr))
				bContinue = false;
			if (bContinue && condStr.nPlatform[0] != PlatforamAll && !IsPlatformType(condStr, info))//平台债
				bContinue = false;
			if (bContinue && condStr.nLocalBond[0] != LocalBondAll && !IsLocalBond(condStr, info))//地方债
				bContinue = false;
			// add  by lbl  NCD  
			if (bContinue && condStr.nNCDRating[0] != NCDRatingAll && !info.CheckNCDRating(condStr))//NCD
				bContinue = false;
			// end 
			if( bContinue && condStr.nIssueYear[0] != 0 && !info.CheckIssueYear(condStr))
				bContinue = false;
			if (bContinue && condStr.nExpireInHoliday == 1 && info.IsExpireInHoliday())//不含假期
				bContinue = false;
			brokerkey.m_nIndex = bondIndex; brokerkey.SetBrokerId(itor->m_company_id);
			if(/*IsEmpty(itor->m_price) && condStr.nHasFlg != 0 ||*/ !bContinue)
				vct_resdel.m_vct.push_back(brokerkey);
			else if(bContinue)vct_result.m_vct.push_back(brokerkey);
		}
	}

	return true;
}


bool CBondContainer::UpdateContainerByCFETS(const BLHCONDITION & condStr, SSBrokerKeyVector& vct_result,
	SSBrokerKeyVector& vct_resdel, const std::list<xQBBestPriceUnit_c> &qblist, bool bSecondaryMarket)
{
	// 底层会改写condStr的sCompanyid字段,因此condStr不能是const
	if (condStr.nCFETSQuoteType < 0 || condStr.nCFETSQuoteType > 2) return false;
	if (strcmp(condStr.sCompanyid, "50") != 0)return false;

	READLOCK(m_mutex);
	
	BrokerKey brokerkey;
	int	nCount = 0;
	char sType[16] = { 0 };
	std::list<xQBBestPriceUnit_c>::const_iterator itor = qblist.begin();
	for (; itor != qblist.end(); itor++)
	{
		int idx = GetBondIndex(itor->m_bondkey, itor->m_listedmarket);
		if (idx < 0)continue;
		const CBondInfo& info = ElementAtR(idx);
		bool bIsCDCAuthValid = info.IsCDCAuthValid();

		bool bGood = false;
		do{
			if (/*condStr.nExchange != 0 && */ info.IsExchange())//交易所债券不显示
				break;
			if (info.IsAddIssueBond()) break; //增续发
			if (condStr.nHasFlg != 0 && !IsCFETSHasPrice(condStr, idx))
				break;
			if (condStr.nBothFlg != 0 && !IsCFETSBilateralPrice(condStr, idx))
				break;
			if (condStr.nSettlement[0] != CBondContainer::StmAll && !CheckCFETSSettlement(condStr, idx))//清算速度
				break;
			if (condStr.nNewFlg != 0 && !info.IsNewBond())
				break;
			if (condStr.nMatFlg != 0 && GetMaturityBond(info))
				break;
			if (condStr.nASemi != 0 && GetRebateBond(info))
				break;
			if (condStr.nMortgt != 0 && !info.IsMortgage())
				break;
			if (condStr.nCrosmk != 0 && !info.IsCrossMarket())
				break;
			if (condStr.nEntrTyp != 0 && !GetSOEenterType(condStr, info))
				break;
			if (!IsEmpty(condStr.sDiffPrice) && !GetCFETSDiffPrice(condStr, idx))
				break;
			if ((!IsEmpty(condStr.sBPrice) || !IsEmpty(condStr.sBPriceEnd)) && !GetCFETSBidCndPrice(condStr, idx))
				break;
			if ((!IsEmpty(condStr.sOPrice) || !IsEmpty(condStr.sOPriceEnd)) && !GetCFETSOfrCndPrice(condStr, idx))
				break;
			if (condStr.nCommonUse[0] != CBondContainer::CommAll && !info.CheckCommonUseType(condStr)) //常用
				break;
			if (condStr.nType[0] != BondAll && !info.CheckBondType(condStr))
				break;
			if (condStr.nIssuerRating[0] != RatingAll && !GetMultiLevel(condStr, info))
				break;
			if (condStr.nOutlookRating[0] != OutlookRatingAll && !GetOutlookRatingLevel(condStr, info))
				break;
			if (condStr.nCDCRating[0] != CBondContainer::CDCRatingAll && !GetCDCRatingLevel(condStr, info))//中债隐含
				break;
			if (condStr.nCSIRating[0] != CBondContainer::CSIRatingAll && !GetCSIRatingLevel(condStr, info))//中证隐含
				break;
			if (condStr.nCBRRating[0] != CBondContainer::CBRRatingAll && !GetCBRRatingLevel(condStr, info))//中债资信
				break;
			if (condStr.nWarrant[0] != WarrAll && !GetWarrType(condStr, info))
				break;
			if (condStr.nCouponType[0] != CouponAll && !GetMultiCouponType(condStr, info))
				break;
			if (condStr.nRight != RightAll && GetRightType(condStr.nRight) != info.IsRight())
				break;
			if (condStr.nRightEx[0] != RightExAll && !info.CheckRightEx(condStr))
				break;
			if (condStr.nRange[0] != RangeAll && !GetMaturityRange(condStr, info, bSecondaryMarket))
				break;
			if (condStr.nMunicp[0] != MunicAll && !GetMunicpType(condStr, info))
				break;
			if (condStr.nInstion[0] != InstAll && !GetMultiInstion(condStr, info))
				break;
			if (condStr.szIssuer[0][0] != '\0' && !info.CheckIssuer(condStr))
				break;
			if (condStr.szSector[0][0] != '\0' && !info.CheckSector(condStr))
				break;
			if (condStr.szSector2021[0][0] != '\0' && !info.CheckSector2021(condStr))
				break;
			if (condStr.szArea[0][0] != '\0' && !info.CheckArea(condStr))
				break;
			if (condStr.szSubType[0][0] != '\0' && !info.CheckBontSubType(condStr))
				break;
			if (condStr.nDebtRating[0] != DRatingNone && !info.CheckDebtRating(condStr))
				break;
			if (condStr.nFinDebt[0] != FinDebtNone && !info.CheckFinDebt(condStr))
				break;
			if (condStr.nPlatform[0] != CBondContainer::PlatforamAll && !IsPlatformType(condStr, info))//平台债
				break;
			if (condStr.nLocalBond[0] != CBondContainer::LocalBondAll && !IsLocalBond(condStr, info))//地方债
				break;			
			if (condStr.nNCDRating[0] != NCDRatingAll && !info.CheckNCDRating(condStr))// add  by lbl  NCD  
				break;
			if (condStr.nIssueYear[0] != 0 && !info.CheckIssueYear(condStr))
				break;
			if (condStr.nETSBond[0] != CBondContainer::ETSBondAll && !IsETSBondType(condStr, info))	 //永续债
				break;
			if (condStr.nCorpBond[0] != CBondContainer::CorpBondAll && !IsCorpBondType(condStr, info))	 //公司债
				break;
			if (condStr.nAssetStatus[0] != CBondContainer::AssetAll && !info.CheckAssetStatus(condStr))//发行
				break;
			if (!IsEmpty(condStr.sBidCdc) && !GetCFETSBidCdcCompare(condStr, idx, bIsCDCAuthValid)) //bid-中债
				break;
			if (!IsEmpty(condStr.sCdcOfr) && !GetCFETSCdcOfrCompare(condStr, idx, bIsCDCAuthValid)) //中债-ofr
				break;
			if (!IsEmpty(condStr.sVolBid) && !GetCFETSBidVol(condStr, idx))//bid.vol
				break;
			if (!IsEmpty(condStr.sVolOfr) && !GetCFETSOfrVol(condStr, idx))//ofr.vol
				break;
			if (condStr.nExpireInHoliday == 1 && info.IsExpireInHoliday())//不含假期
				break;				
			bGood = true;
		} while (0);

		FMTBUF(sType, "%d", condStr.nCFETSQuoteType);
		brokerkey.m_nIndex = idx; brokerkey.SetBrokerId(sType);

		if (!bGood){
			CBrokerKeyVector::iterator itKey = std::find(vct_resdel.m_vct.begin(), vct_resdel.m_vct.end(), brokerkey);
			if (itKey == vct_resdel.m_vct.end())//去重
				vct_resdel.m_vct.push_back(brokerkey);
		}
		else{
			CBrokerKeyVector::iterator itKey = std::find(vct_result.m_vct.begin(), vct_result.m_vct.end(), brokerkey);
			if (itKey == vct_result.m_vct.end())//去重
				vct_result.m_vct.push_back(brokerkey);
		}
		//NETLOG("[LANCETEST] code=%s, price=%s, bGood=%s", info.GetCombBondCode(), itor->m_price, bGood ? "true" : "false");
		//NETLOG("%s has been pushed --> vct_result, ver = %d", itor->m_bond_shorname, bContinue ? "vct_result" : "vct_resdel", itor->m_version);
	}

	return true;
}

int CBondContainer::GetSize() 
{ 
	READLOCK(m_mutex);
	return m_vctbond.size(); 
}
int CBondContainer::GetSizeImpl()
{
	return m_vctbond.size();
}

const CBondInfo& CBondContainer::ElementAtR(int nIndex)const
{
	//NEEDCHECK
	////SP_ASSERT(nIndex >= 0 && nIndex < (int)m_vctbond.size());
	if (nIndex < 0 || nIndex >= (int)m_vctbond.size()){
		return m_bond_null;
	}
	USE_BOND(CBondInfo, nIndex);
	return *m_vctbond[nIndex];
}

CBondInfo& CBondContainer::ElementAtW(int nIndex)
{
	/*
		之所以引入m_bond_null_write,是因为ElementAtW可能返回m_bond_null
		外界不加判断就改写此CBondInfo,可能导致m_bond_null改变
		以此确保m_bond_null永远不变	
	*/
	//NEEDCHECK
	////SP_ASSERT(nIndex >= 0 && nIndex < (int)m_vctbond.size());
	if (nIndex < 0 || nIndex >= (int)m_vctbond.size()){
		return m_bond_null_write;
	}
	USE_BOND(CBondInfo, nIndex);
	return *m_vctbond[nIndex];
}

CBondCompanyRep* CBondContainer::GetCompanyRep(int nIndex)
{
	return BrokerRepMng->GetReport(nIndex);
}

CBondBankRep* CBondContainer::GetBankRep(int nIndex)
{
	return BankRepMng->GetReport(nIndex);
}

CBondBankRep* CBondContainer::GetClntRep(int nIndex)
{
	return BankClientRepMng->GetReport(nIndex);
}

CXCQuoteRep* CBondContainer::GetXCQuote(int nIndex)
{
	return XCQuoteRepMng->GetReport(nIndex);
}

CCFETSQuoteRep* CBondContainer::GetCFETSQuote(int nIndex)
{
	return CfetsRepMng->GetReport(nIndex);
}

CCFETSDealQuoteRep* CBondContainer::GetCFETSDealQuote(int nIndex)
{
	return CfetsDealRepMng->GetReport(nIndex);
}

void CBondContainer::ClearVersion()
{
	WRITELOCK(m_mutex);
	m_verarr.clear();
}

void CBondContainer::ClearVersion(int clrFlag)
{	
	WRITELOCK(m_mutex);
	if(clrFlag==LIQ_CLR_BESTPRICE_ALL)
	{
		ClearVersion();
	}
	else
	{
		std::map<std::string, int>::iterator  pos;
		for (pos=m_verarr.begin(); pos!=m_verarr.end();)
		{
			if ((clrFlag==LIQ_CLR_BESTPRICE_BROKE) &&  (pos->first!="e") && (pos->first!="c"))
			{
				m_verarr.erase(pos++);
			}
			else if((clrFlag==LIQ_CLR_BESTPRICE_CFETS) && (pos->first == "c"))
			{
				m_verarr.erase(pos++);
			}
			else if((clrFlag==LIQ_CLR_BESTPRICE_EXCHANGE) && (pos->first == "e"))
			{
				m_verarr.erase(pos++);
			}
			else
			{
				++pos;
			}
		}
	}
}

int CBondContainer::GetVersionById(const std::string& szKey)
{
	READLOCK(m_mutex);
	if(m_verarr.size()>0)
	{
		std::map<std::string, int>::iterator it = m_verarr.find(szKey);
		if(it!=m_verarr.end())
			return it->second;
	}
	return 0;
}

void CBondContainer::UpdateVersionById(const std::string& szKey,int nVerNo,time_t nTime)
{
	WRITELOCK(m_mutex);
	m_verarr[szKey] = nVerNo;
	if (nTime <= 0) nTime = ServerTimeMgr::instance().serverTime();
	QDateTime qdt;
	qdt.setTimeSpec(Qt::UTC);//TODO OK?
	qdt.setSecsSinceEpoch(nTime);
	m_nLastReportDate = qdt.date().year() * 10000 + qdt.date().month() * 100 + qdt.date().day();
}

bool CBondContainer::CheckCFETSDayChanged()
{
	CReportManagerBase::Scoped l(CfetsRepMng->GetMutex());
	return CfetsRepMng->isDayChanged();
}

void CBondContainer::ClearCFETSDealQuoteVersion()
{
	CReportManagerBase::Scoped l(CfetsDealRepMng->GetMutex());
	CfetsDealRepMng->ClearVersion();
}

int	CBondContainer::GetCFETSDealQuoteVersion()
{
	CReportManagerBase::Scoped l(CfetsDealRepMng->GetMutex());
	return CfetsDealRepMng->GetVersion();
}

bool CBondContainer::CheckCFETSDealDayChanged()
{
	CReportManagerBase::Scoped l(CfetsDealRepMng->GetMutex());
	return CfetsDealRepMng->isDayChanged();
}

bool CBondContainer::GetStateType(const BLHCONDITION& Cond,const CBondInfo& Info)
{//=全部，1=今日簿记建档，2=当日发行，3=当日公告

	bool bRet = false;
	switch (Cond.nStateType)
	{
	case 1:
		bRet = IsInToday(this,Info.GetAuctionDateStart());
		break;
	case 2:
		bRet = IsInToday(this,Info.GetIssueStartDate());
		break;
	case 3:
		bRet = IsInToday(this,Info.GetAnnounceDate());
		break;
	default:
		break;
	}

	return bRet;
}

bool CBondContainer::GetIssueStartDate(const BLHCONDITION& Cond,const CBondInfo& Info)
{
	const char *pIssueStartDate = Info.GetIssueStartDate();
	if (!IsEmpty(pIssueStartDate))
	{
		int nTime = atoi(pIssueStartDate);
		if (nTime >= atoi(Cond.szIssueDateB) && nTime <= atoi(Cond.szIssueDateE))
			return true;
	}
	return false;
}

CBondInfo * CBondContainer::GetBond( const std::string &sBondKey, const std::string &sMarket ) 
{
	return GetBond(sBondKey+"."+sMarket);
}

CBondInfo * CBondContainer::GetBond( const std::string &sCombBondKey ) 
{
	int bid = GetBondIndexImpl(sCombBondKey.c_str(), sCombBondKey.size());
	return GetBond(bid);
}

CBondInfo * CBondContainer::GetBond( int nBondIndex ) 
{
	if(nBondIndex < 0 || nBondIndex >= (int)m_vctbond.size())return nullptr;
	return m_vctbond[nBondIndex]; 
}

int CBondContainer::GetBondIndex( const std::string &sBondKey, const std::string &sMarket )
{
	char keybuf[64] = { 0 };
	if (sBondKey.size() + 1 + sMarket.size() >= sizeof(keybuf))
		return -1;

	int len=FIELDCOPY(keybuf, sBondKey.c_str());
	keybuf[len++] = '.';
	len += FIELDCOPYN(keybuf + len, sizeof(keybuf) - len, sMarket.c_str());
	return GetBondIndexImpl(keybuf,len);
}
int CBondContainer::GetBondIndex(const char* sBondKey, const char* sMarket)
{
	char keybuf[64] = { 0 };
	int len = FIELDCOPY(keybuf, sBondKey);
	if (len + 1 < sizeof(keybuf))
	{
		keybuf[len++] = '.';
		len += FIELDCOPYN(keybuf + len, sizeof(keybuf) - len, sMarket);
		return GetBondIndexImpl(keybuf, len);
	}
	return -1;
}
int CBondContainer::GetBondIndex( const std::string &sCombBondKey )
{
	return GetBondIndexImpl(sCombBondKey.c_str(), sCombBondKey.size());
}
bool CBondContainer::IsValidIndex(int index)
{
	if (index < 0)return false;
	int nsize = GetSizeImpl();
	return index < nsize ? true : false;
}
int CBondContainer::GetBondIndexImpl(const char* sCombBondKey, int len)
{
	void* pArrayID = nullptr;
	READLOCK(m_mutex);
	if (m_keymap.Lookup(sCombBondKey, pArrayID))
	{
		uint64_t uArrayID = (uint64_t)pArrayID;
		return (int)uArrayID;
	}
	return -1;
}
int CBondContainer::GetBondIndexByCodeImpl(const char* sCombBondCode, int len)
{
	void* pArrayID = nullptr;
	READLOCK(m_mutex);
	if (m_map.Lookup(sCombBondCode, pArrayID))
	{
		uint64_t uArrayID = (uint64_t)pArrayID;
		return (int)uArrayID;
	}
	return -1;
}
bool CBondContainer::GetFreezeReport( const char * szCompanyID )
{
	if ( szCompanyID == nullptr )
	{
		return false;
	}
	return false;
}

bool CBondContainer::RetrieveSupperNewBonds(const BLHCONDITION & condStr,std::vector<int>& array_result )
{
	if( condStr.nBrokId[0]==0 && IsEmpty(condStr.sCompanyid) )
		return false;

	HUGELOCK(m_mutex);
	if(condStr.isAllin()){
		int nSize = GetSize();
		for( int i=0; i<nSize; i++ )//BIGLOOP
			array_result.push_back(i);
	}
	else
	{
		int	nCount	=	0;
		int nSize = GetSize();
		for( int i=0; i<nSize; i++ )//BIGLOOP
		{
			bool bContinue = true;
			const CBondInfo	& info = ElementAtR(i);

			if( bContinue && condStr.nType[0] != BondSC_All && !info.ShortCheckBondType(condStr))
				bContinue = false;
			if( bContinue && condStr.nIssuerRating[0] != RatingAll && !GetMultiLevel(condStr,info))
				bContinue = false;

			if (bContinue && condStr.nOutlookRating[0] != OutlookRatingAll && !GetOutlookRatingLevel(condStr, info))
				bContinue = false;

			if (bContinue && condStr.nCDCRating[0] != CDCRatingAll && !GetCDCRatingLevel(condStr, info))
				bContinue = false;
			if (bContinue && condStr.nCSIRating[0] != CSIRatingAll && !GetCSIRatingLevel(condStr, info))
				bContinue = false;
			if (bContinue && condStr.nCBRRating[0] != CBRRatingAll && !GetCBRRatingLevel(condStr, info))
				bContinue = false;

			if(bContinue && condStr.nDeadLineRange[0] != DL_RangeAll && !GetDeadLineRange(condStr,info))
				bContinue = false;
			if( bContinue && condStr.nCreditBond != 0 && !info.IsSuperNewBond(condStr))
				bContinue = false;
			if( bContinue && !info.IsInDays(condStr))
				bContinue = false;
			if( bContinue )
			{
				array_result.push_back(i);
				nCount	++;
			}
		}
	}

	return true;
}

bool CBondContainer::CompareRemainingDay( std::string& sPeriod1,std::string& sPeriod2 )
{
	double dDay1 = CBondContainer::CalcRemainingDay(sPeriod1);
	double dDay2 = CBondContainer::CalcRemainingDay(sPeriod2);
	if ( dDay1 == dDay2 )  //365D小于1Y小于366D
	{
		bool bStatus1 = sPeriod1.find("Y") != std::string::npos;
		bool bStatus2 = sPeriod2.find("Y") != std::string::npos;
		if ( bStatus1 && !bStatus2 )
		{
			return false;
		}
		else if (!bStatus1 && bStatus2 )
		{
			return true;
		}

		return false;
	}

	return dDay1 < dDay2;
}

bool CBondContainer::GetLatestCompanyRepByBondIndex( int nBondIndex,REPORT &stRep,bool bBuyPool )
{
	if (nBondIndex < 0 || nBondIndex >= GetSize())
		return false;
	memset( &stRep, 0, sizeof(REPORT) );
	CBondCompanyRep* ptmp = GetCompanyRep(nBondIndex);
	return ptmp ? ptmp->GetLatestReport(stRep, bBuyPool) : false;
}


bool CBondContainer::GetAdditionList(int nID, std::set<int>* &pSet)
{
	pSet = nullptr;
	READLOCK(m_mutex);
	if(nID < 0 || nID >= (int)m_vctbond.size())return false;

	std::map<int, std::set<int>>::iterator it = m_mapaddi.find(nID);
	if(it != m_mapaddi.end()){
		pSet = &(it->second);
		return true;
	}
	return false;
}

bool CBondContainer::IsHyHasPrice(const BLHCONDITION & Cond, int nID )
{
	//TODO
	return false;
}


bool CBondContainer::CheckSettlement(const BLHCONDITION & Cond, int nID)
{
	class SettlementChecker : public CBondCompanyRep::ApplyCallback {
		bool		m_result;
		const BLHCONDITION& m_cond;
	public:
		SettlementChecker(const BLHCONDITION& cond) :m_result(false), m_cond(cond) {}
		bool operator()(CBondCompanyRep* ptmp) {
			m_result = false;
			if (ptmp)
				ptmp->ApplyAccess(true, "", this);
			return m_result;
		}
		virtual bool DoAccess(const REPORT& rpt)
		{
			if (CBondContainer::CheckSettlement(m_cond, rpt.m_bidinfo))
			{
				m_result = true;
				return false;
			}
			if (CBondContainer::CheckSettlement(m_cond, rpt.m_askinfo))
			{
				m_result = true;
				return false;
			}
			return true;//表示继续遍历
		}
	};

	if (Cond.nSettlement[0] == StmAll)return true;
	if (Cond.nSettlement[0] == StmNone)return false;

	if (strlen(Cond.sCompanyid) <= 0)
	{
		CBondCompanyRep* ptmp = GetCompanyRep(nID);
		if (!ptmp)return false;
		SettlementChecker checker(Cond);
		return checker(ptmp);
	}
	else
	{
		REPORT stRep = { 0 };
		if (!GetCompanyRepById(nID, Cond.sCompanyid, stRep))return false;
		if (CheckSettlement(Cond, stRep.m_bidinfo))return true;
		if (CheckSettlement(Cond, stRep.m_askinfo))return true;
		return false;
	}
	return false;
}

bool CBondContainer::CheckSettlement(const BLHCONDITION& Cond, const PRICE& prc)
{
	PRICE_SETTLEMENT_LIST lst;
	DecodeSettlement(prc, lst);
	if (lst.size() <= 0)return false;

	int sz = sizeof(Cond.nSettlement) / sizeof(int);
	for (int i = 0; i < sz; i++)
	{
		switch (Cond.nSettlement[i])
		{
		case StmNone:
			return false;
			break;
		case StmAll:
			return true;
			break;
		case StmT0:
			for (auto& it : lst)
			{
				if (0 != (it.m_type & 0x1))
				{
					return true;
				}
			}
			break;
		case StmT1:
			for (auto& it : lst)
			{
				if (0 != (it.m_type & 0x2))
				{
					return true;
				}
			}
			break;
		case StmFwd:
			for (auto& it : lst)
			{
				if (0 != (it.m_type & 0x4))
				{
					return true;
				}
			}
			break;
		case StmSpot:
			for (auto& it : lst)
			{
				if (0 != (it.m_type & 0x3))
				{
					return true;
				}
			}
			break;
		default:
			break;
		}
	}
	return false;
}

bool CBondContainer::GetVolBidCompare(const BLHCONDITION & Cond, int nID)
{
	class GetBidVolCompareCallback : public CBondCompanyRep::ApplyCallback {
		bool			m_result;
		int				m_nBondIndex;
		const BLHCONDITION& m_cond;
	public:
		GetBidVolCompareCallback(const BLHCONDITION& cond, const int nBondIndex) :m_result(false),
			m_cond(cond), m_nBondIndex(nBondIndex) {}
		bool GetResult()const { return m_result; }
		virtual bool DoAccess(const REPORT& quote)//true表示可继续,false表示中断
		{
			if (IsEmpty(quote.m_bidinfo.m_sVolume) || strcmp(quote.m_bidinfo.m_sVolume, "--") == 0)
			{
				//无效报量
				m_result = false;
			}
			else
			{
				double fFilterVol = atof(m_cond.sVolBid);
				std::vector<std::string> vctDest;
				_SplitStr(vctDest, quote.m_bidinfo.m_sVolume, "+");
                for (auto it = vctDest.begin(); it != vctDest.end(); ++it)
				{
					double fVolumn = atof(it->c_str());
					if (m_cond.nVolBpcCnd == 0) //0 表示[<= ], 1 表示[>= ]
					{
						if (fVolumn < fFilterVol + 0.000001)
						{
							m_result = true;
							return false;
						}
					}
					else
					{
						if (fVolumn > fFilterVol - 0.000001)
						{
							m_result = true;
							return false;
						}
					}
				}
			}
			return m_result ? false : true;
		}
	};

	if (IsEmpty(Cond.sVolBid))return true;

	CBondCompanyRep* ptmp = GetCompanyRep(nID);
	if (!ptmp)return false;

	GetBidVolCompareCallback accessor(Cond, nID);
	ptmp->ApplyAccess(IsEmpty(Cond.sCompanyid), Cond.sCompanyid, &accessor);
	if (accessor.GetResult())
		return true;

	return false;
}

bool CBondContainer::GetVolOfrCompare(const BLHCONDITION & Cond, int nID )
{
	
	class GetOfrVolCompareCallback : public CBondCompanyRep::ApplyCallback {
		bool			m_result;
		int				m_nBondIndex;
		const BLHCONDITION& m_cond;
	public:
		GetOfrVolCompareCallback(const BLHCONDITION& cond, const int nBondIndex) :m_result(false),
			m_cond(cond), m_nBondIndex(nBondIndex) {}
		bool GetResult()const { return m_result; }
		virtual bool DoAccess(const REPORT& quote)//true表示可继续,false表示中断
		{
			if (IsEmpty(quote.m_askinfo.m_sVolume) || strcmp(quote.m_askinfo.m_sVolume, "--") == 0)
			{
				//无效报量
				m_result = false;
			}
			else
			{
				double fFilterVol = atof(m_cond.sVolOfr);
				std::vector<std::string> vctDest;
				_SplitStr(vctDest, quote.m_askinfo.m_sVolume, "+");
                for (auto it = vctDest.begin(); it != vctDest.end(); ++it)
				{
					double fVolumn = atof(it->c_str());
					if (m_cond.nVolOpcCnd == 0) //0 表示[<= ], 1 表示[>= ]
					{
						if (fVolumn < fFilterVol + 0.000001)
						{
							m_result = true;
							return false;
						}
					}
					else
					{
						if (fVolumn > fFilterVol - 0.000001)
						{
							m_result = true;
							return false;
						}
					}
				}
			}
			return m_result ? false : true;
		}
	};

	if (IsEmpty(Cond.sVolOfr))return true;

	CBondCompanyRep* ptmp = GetCompanyRep(nID);
	if (!ptmp)return false;

	GetOfrVolCompareCallback accessor(Cond, nID);
	ptmp->ApplyAccess(IsEmpty(Cond.sCompanyid), Cond.sCompanyid, &accessor);
	if (accessor.GetResult())
		return true;

	return false;
}

bool CBondContainer::GetExchangeType(const BLHCONDITION & Cond,const CBondInfo & Info)
{
	switch( Cond.nExchangeType )
	{
	case kExchAll:
		return true;
		break;
	case kExchSSE:
		return strcmp(Info.GetListedMarket(),"SSE") == 0;
		break;
	case kExchSZE:
		return strcmp(Info.GetListedMarket(),"SZE") == 0;
	    break;
	default:
	    break;
	}
	
	return false;
}

bool CBondContainer::GetBidCdcCompare(const BLHCONDITION & Cond, int nID)
{
	class GetBidCdcCompareCallback : public CBondCompanyRep::ApplyCallback {
		bool			m_result;
		int				m_nBondIndex;
		bool			m_bIsCDCAuthValid;
		const BLHCONDITION& m_cond;
	public:
		GetBidCdcCompareCallback(const BLHCONDITION& cond, const int nBondIndex, bool bIsCDCAuthValid) :m_result(false),
			m_cond(cond), m_nBondIndex(nBondIndex), m_bIsCDCAuthValid(bIsCDCAuthValid) {}
		bool GetResult()const { return m_result; }
		virtual bool DoAccess(const REPORT& quote)//true表示可继续,false表示中断
		{
			if (IsEmpty(quote.m_bidinfo.m_sPrice) || strcmp(quote.m_bidinfo.m_sPrice, "Bid") == 0
				|| strcmp(quote.m_bidinfo.m_price_status, "0") == 0/*||strcmp(info.GetEstPrice(),"0")==0*/
				|| (!IsEmpty(quote.m_bidinfo.m_quotetype) && atoi(quote.m_bidinfo.m_quotetype) == 0))//有意向
			{
				//无效价格，或者无效估值
				m_result = false;
			}
			else
			{
				if (quote.m_bidinfo.m_yield_price[0] == '\0')
				{
					m_result = false;
					return true;
				}
				double fYield = atof(quote.m_bidinfo.m_yield_price);
				if (quote.m_company_id[0] != 'e' && atoi(quote.m_bidinfo.m_quotetype) != 3)
				{
					CBondInfo* pInfo = CBondContainer::instance().GetBond(m_nBondIndex);
					if (pInfo && (pInfo->IsBondABS() || pInfo->IsTransBond()))
					{
						if (fYield <= 0 || fYield >= 30)
						{
							m_result = false;
							return true;
						}
					}
				}

				double dDiff = CBondCDCPriceInfo::instance().GetYesterdayCDCPriceGap(m_bIsCDCAuthValid, m_nBondIndex, CBondCDCPriceInfo::price_type_yield, true, quote.m_bidinfo.m_yield_price, INVALID_CDC_VALUE, false);
				if (dDiff < INVALID_CDC_VALUE + 1e-6)
				{
					m_result = false;
					return true;
				}
				m_result = true;
				if (m_cond.sBidCdc[0] != 0)
				{
					if (dDiff < atof(m_cond.sBidCdc) - 1e-6)
					{
						m_result = false;
						return true;
					}
				}
				if (m_cond.sBidCdcEnd[0] != 0)
				{
					if (dDiff > atof(m_cond.sBidCdcEnd) + 1e-6)
					{
						m_result = false;
						return true;
					}
				}
			}
			return m_result ? false : true;
		}
	};

	if (IsEmpty(Cond.sBidCdc))return true;

	int nOptType = CBondCDCPriceInfo::est_type_invalid;

	CBondCompanyRep* ptmp = GetCompanyRep(nID);
	if (ptmp)
	{
		bool bIsCDCAuthValid = true;
		CBondInfo* pInfo = nullptr;
		pInfo = GetBond(nID);
		if (pInfo->IsCDCAuthValid()) {
			bIsCDCAuthValid = pInfo->IsCDCAuthValid();
		}
		GetBidCdcCompareCallback accessor(Cond, nID, bIsCDCAuthValid);
		ptmp->ApplyAccess(IsEmpty(Cond.sCompanyid), Cond.sCompanyid, &accessor);
		if (accessor.GetResult())
			return true;
	}
	return false;
}

bool CBondContainer::GetCdcOfrCompare(const BLHCONDITION & Cond, int nID)
{
	if (IsEmpty(Cond.sCdcOfr))return true;

	CBondCompanyRep* ptmp = GetCompanyRep(nID);
	if (ptmp && ptmp->GetSize() > 0)
	{
		class GetCdcOfrCompareCallback : public CBondCompanyRep::ApplyCallback {
			bool			m_result;
			int				m_nBondIndex;
			bool			m_bIsCDCAuthValid;
			const BLHCONDITION& m_cond;
		public:
			GetCdcOfrCompareCallback(const BLHCONDITION& cond, int nId, bool bIsCDCAuthValid) :m_result(false),
				m_cond(cond), m_nBondIndex(nId), m_bIsCDCAuthValid(bIsCDCAuthValid) {}
			bool GetResult()const { return m_result; }
			virtual bool DoAccess(const REPORT& quote)//true表示可继续,false表示中断
			{
				if (IsEmpty(quote.m_askinfo.m_sPrice) || strcmp(quote.m_askinfo.m_sPrice, "Ofr") == 0 ||
					strcmp(quote.m_askinfo.m_price_status, "0") == 0/*||strcmp(info.GetEstPrice(),"0")==0*/)
				{
					//无效价格，或者无效估值
					m_result = false;
				}
				else
				{
					if (quote.m_askinfo.m_yield_price[0] == '\0')
					{
						m_result = false;
						return true;
					}
					double fYield = atof(quote.m_askinfo.m_yield_price);
					if (atoi(quote.m_askinfo.m_quotetype) != 3)
					{
						CBondInfo* pInfo = CBondContainer::instance().GetBond(m_nBondIndex);
						if (pInfo && (pInfo->IsBondABS() || pInfo->IsTransBond()))
						{
							if (fYield <= 0 || fYield >= 30)
								return false;
						}
					}

					double dDiff = CBondCDCPriceInfo::instance().GetYesterdayCDCPriceGap(m_bIsCDCAuthValid, m_nBondIndex, CBondCDCPriceInfo::price_type_yield, false, quote.m_askinfo.m_yield_price, INVALID_CDC_VALUE, false);
					if (dDiff < INVALID_CDC_VALUE + 1e-6)
					{
						m_result = false;
						return true;
					}
					if (m_cond.sCdcOfr[0] != 0)
					{
						if (dDiff < atof(m_cond.sCdcOfr) - 1e-6)
						{
							m_result = false;
							return true;
						}
					}
					if (m_cond.sCdcOfrEnd[0] != 0)
					{
						if (dDiff > atof(m_cond.sCdcOfrEnd) + 1e-6)
						{
							m_result = false;
							return true;
						}
					}
					m_result = true;
				}
				return m_result ? false : true;
			}
		};
		bool bIsCDCAuthValid = true;
		CBondInfo* pInfo = nullptr;
		pInfo = GetBond(nID);
		if (pInfo->IsCDCAuthValid()) {
			bIsCDCAuthValid = pInfo->IsCDCAuthValid();
		}
		GetCdcOfrCompareCallback accessor(Cond, nID, bIsCDCAuthValid);
		ptmp->ApplyAccess(IsEmpty(Cond.sCompanyid), Cond.sCompanyid, &accessor);
		if (accessor.GetResult())
			return true;
	}
	return false;
}

bool CBondContainer::GetMaturityRangeEx(const BLHCONDITION & Cond,const CBondInfo & Info )
{
	//NEEDCHECK
	// GetRemainPeriod 是必须对info进行更改,且有安全风险
	bool bRes = false;
	int nSize = sizeof(Cond.nRange)/sizeof(uint32_t);
	for( int i=0; i<nSize; i++)
	{
		switch( Cond.nRange[i] )
		{
		case DL_RangeDate:
			if(IsEmpty(Cond.sDate1) && IsEmpty(Cond.sDate2))return true;
			break;
		default:
			break;
		}
	}
	if (IsEmpty(Info.GetMaturityDate()))
	{
		//LOGWARN("GetMaturityDate is empty");
		return false;
	}

	time_t t = ServerTimeMgr::instance().serverTime();
	std::string str = Info.GetRemainPeriod(t);
	long ldays = (LONG)CalcRemainingDay(str);
	double fYear = ldays/365.0;

	double lfStartDLYear = 0.0;
	double lfEndDLYear = 0.0;
	//判断条件：前开后闭
	for( int i=0; i<nSize; i++)
	{
		if(Cond.nRange[i]==0x00)
			return false;

		switch( Cond.nRange[i] )
		{
		case DL_Range1:
			{
				lfStartDLYear = (1-1)/12.0;
				lfEndDLYear = (1+1)/12.0;
			}
			break;
		case DL_Range2:
			{
				lfStartDLYear = (3-1)/12.0;
				lfEndDLYear = (3+1)/12.0;
			}
			break;
		case DL_Range3:
			{
				lfStartDLYear = (6-1)/12.0;
				lfEndDLYear = (6+1)/12.0;
			}
			break;
		case DL_Range4:
			{
				lfStartDLYear = (9-2)/12.0;
				lfEndDLYear = (9+2)/12.0;
			}
			break;
		case DL_Range5:
			{
				lfStartDLYear = 1-2.0/12.0;
				lfEndDLYear = 1+2.0/12.0;
			}
			break;
		case DL_Range6:
			{
				lfStartDLYear = 3-2.0/12.0;
				lfEndDLYear = 3+2.0/12.0;
			}
			break;
		case DL_Range7:
			{
				lfStartDLYear = 5-3.0/12.0;
				lfEndDLYear = 5+3.0/12.0;
			}
			break;
		case DL_Range8:
			{
				lfStartDLYear = 7-4.0/12.0;
				lfEndDLYear = 7+4.0/12.0;
			}
			break;
		case DL_Range9:
			{
				lfStartDLYear = 10-4.0/12.0;
				lfEndDLYear = 10+4.0/12.0;
			}
			break;
		case DL_Range10:
			{
				lfStartDLYear = 9.5;
				lfEndDLYear = 10000.0;
			}
			break;
		case DL_RangeDate:
			{
				lfStartDLYear = atof(Cond.sDate1);
				lfEndDLYear = atof(Cond.sDate2);
			}
			break;
		case DL_Range21:
			{
				lfStartDLYear = 1.00001;
				lfEndDLYear = 10000.0;
			}
			break;
		default:
			break;
		}

		if( fYear <= lfEndDLYear && fYear>lfStartDLYear) return true;
		else continue;
	}

	return bRes;
}

bool CBondContainer::CheckVersion(){//检查报价版本号，如果跨天，清数据
	QDateTime t = QDateTime::fromSecsSinceEpoch(ServerTimeMgr::instance().serverTime());
	int serverDate = t.date().year() * 10000 + t.date().month() * 100 + t.date().day();
	if (m_nLastReportDate != serverDate) {
		ClearReport();
		return true;
	}
	return false;
}

bool CBondContainer::CheckBondCdcValid(const char * szBondKey, const char * szListedMarket)
{
	int nID = GetBondIndex(szBondKey, szListedMarket);
	if (nID < 0 || nID >= GetSize())return false;

	const CBondInfo& info = ElementAtR(nID);
	return info.IsCDCAuthValid();
}

bool CBondContainer::CheckBondCdcValid(const char * szCombBondKey)
{
	int nID = GetBondIndex(szCombBondKey);
	if (nID < 0 || nID >= GetSize())return false;

	const CBondInfo& info = ElementAtR(nID);
	return info.IsCDCAuthValid();
}

void CBondContainer::DumpStatus(int mode)const
{
}

void CBondContainer::DecodeSettlement(const PRICE& price, PRICE_SETTLEMENT_LIST & pdList)
{
	if (price.m_id[0] == '\0')return;
//	BASSERT(price.m_interpret[0] != '\0');
	DecodeSettlement(price.m_interpret, pdList);
}

#ifndef WIN32
#define strncpy_s strncpy
#endif
void _decode_interpret(price_settlement& unit, const char* &P, const char* &lastP, int &step){
	switch (step)
	{
	case 0://量
		//BASSERTS(P - lastP < 16, "DecodeError");
		if (P != lastP)strncpy_s(unit.m_vol, lastP, P - lastP);
		P++;
		lastP = P;
		step++;
		break;
	case 1://原始备注
		//BASSERTS(P - lastP < 64, "DecodeError");
		if (P != lastP)strncpy_s(unit.m_desc, lastP, P - lastP);
		P++;
		lastP = P;
		step++;
		break;
	case 2://清算速度old
		////BASSERTS(P - lastP == 1, "DecodeError");
		if(P != lastP)
			unit.m_typeold = *lastP;
		P++;
		lastP = P;
		step++;
		break;
	case 3://需请示，必须请示
		////BASSERTS(P - lastP == 1, "DecodeError");
		if(P != lastP)
			unit.m_bargin = *lastP;
		P++;
		lastP = P;
		step++;
		break;
	case 4://清算速度
		////BASSERTS(P - lastP == 1, "DecodeError");
		if (P != lastP && *lastP > '0')
			unit.m_type = *lastP - '0';
		P++;
		lastP = P;
		step++;
		break;
	default://向后兼容
		P++;
		lastP = P;
		step++;
		break;
	}
}

void _insertlist_interpret(PRICE_SETTLEMENT_LIST& lst, price_settlement& unit)
{
	if (unit.m_type == 0x0 && unit.m_typeold != '\0')
	{
		if (unit.m_typeold == '0')
			unit.m_type = 0x1;
		else if (unit.m_typeold == '1')
			unit.m_type = 0x2;
		else if (unit.m_typeold == '2')
			unit.m_type = 0x4;
	}

	lst.push_back(unit);
}

void CBondContainer::DecodeSettlement(const char* intp, PRICE_SETTLEMENT_LIST& pdList)
{
	if (intp == nullptr || intp[0] == '\0')
		return;

	const char* P = intp;
	int pos = 0;
	int sz = strlen(intp) + 1;//'\0'

	int step = 0;
	const char* lastP = P;
	price_settlement unit;
	while (pos < sz)
	{
		if (*P == ',')
		{
			_decode_interpret(unit, P, lastP, step);
		}
		else if (*P == ';')
		{
			_decode_interpret(unit, P, lastP, step);
			_insertlist_interpret(pdList, unit);
			memset(&unit, 0, sizeof(unit));
			step = 0;
		}
		else if (*P == '\0')
		{
			_decode_interpret(unit, P, lastP, step);
			_insertlist_interpret(pdList, unit);
			memset(&unit, 0, sizeof(unit));
			break;
		}
		else
		{
			P++;
		}
		pos++;
	}
}

bool CBondContainer::CheckPrincipalPayType(const BLHCONDITION& Cond, const CBondInfo& Info) {
	if (Cond.nPrincipalPayType[0] == PPTNone) {
		return false;
	}
	if (Cond.nPrincipalPayType[0] == PPTAll) {
		return Info.IsAmortizing() || Info.IsNonAmortizing();
	}

	int sz = sizeof(Cond.nPrincipalPayType) / sizeof(int);
	for (int i = 0; i < sz; i++) {
		switch (Cond.nPrincipalPayType[i]) {
		case PPTAmortizing:
			if (Info.IsAmortizing()) {
				return true;
			}
			break;
		case PPTNonAmortizing:
			if (Info.IsNonAmortizing()) {
				return true;
			}
			break;
		default:
			break;
		}
	}
	return false;
}
